Lecc 3

  • Uploaded by: maria
  • 0
  • 0
  • December 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Lecc 3 as PDF for free.

More details

  • Words: 6,982
  • Pages: 35
Informática Gráfica abril, 2007

Librerías de Recursos: Aux y Glut

Rubén de la Peña Ramos Ana de la Viuda López Pablo Sánchez Manzano

Departamento de Informática y Automática Universidad de Salamanca

Tabla de Contenidos

1.

Introducción __________________________________________________ 1

2.

Registro de Funciones Callback___________________________________ 3

3.

La librería AUX de OpenGL______________________________________ 5 3.1.

Introducción ____________________________________________________ 5

3.2.

Funciones de la librería AUX ______________________________________ 5

3.2.1 3.2.2 3.2.3 3.2.4 3.2.5

4.

La librería Glut de OpenGL _____________________________________ 15 4.1.

Introducción ___________________________________________________ 15

4.2.

Funciones de la librería Glut______________________________________ 16

4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6

5.

Inicialización_________________________________________________________5 Manejo de ventanas ___________________________________________________6 Proceso de eventos ____________________________________________________8 Uso del teclado y del ratón _____________________________________________10 Objetos predefinidos __________________________________________________13

Inicialización________________________________________________________16 Manejo de ventanas __________________________________________________18 Procesado de eventos _________________________________________________20 Manejo de menús ____________________________________________________23 Fuentes de texto _____________________________________________________24 Objetos predefinidos __________________________________________________26

Conclusión___________________________________________________ 27

Informática Gráfica

i

ii

Informática Gráfica

Lista de Figuras Figura 01: Ejemplo de inicialización en Aux _______________________________________________6 Figura 02: Máquina de estados de la biblioteca GLUT ______________________________________16 Figura 03: Ejemplo de inicialización en GLUT ____________________________________________18 Figura 04: Ejemplo de múltiples ventanas y subventanas. ____________________________________19 Figura 05: Pseudocódigo de un programa basado en eventos _________________________________21 Figura 06: Ejemplo de registro de eventos en GLUT ________________________________________22 Figura 07: Ejemplo de creación de un menú en GLUT ______________________________________24 Figura 08: Ejemplo de manejo de textos en GLUT __________________________________________25 Figura 09: Rutina para escribir en texto en pantalla con GLUT _______________________________25

Informática Gráfica

iii

iv

Informática Gráfica

Lista de Tablas Tabla 01: Librerías y Ficheros de OpenGL ________________________________________________1 Tabla 02: Valores para las características de ventana________________________________________6 Tabla 03: Constantes Teclado OpenGL __________________________________________________11 Tabla 04: Constantes de visualización ___________________________________________________17 Tabla 05: Comparación AUX – GLUT ___________________________________________________27

Informática Gráfica

v

vi

Informática Gráfica

1.

Introducción

Este capítulo se centra en las bibliotecas que complementan a la API OpenGL. Las dos más conocidas son Aux y Glut, ambas acompañan a OpenGL y se pueden obtener en las diversas versiones de ésta. Aux es la más antigua de las dos y presenta algunas limitaciones que Glut soluciona. Las funciones del núcleo de OpenGL se limitan a facilitar las operaciones que podrían denominar gráficas puras, no existiendo procedimientos para el uso de matrices, funciones cuadráticas y similares o funciones de manejo de ventanas y eventos. Es por esta razón por la que se utilizan bibliotecas complementarias que actuarán como una extensión de OpenGL para facilitar dichas operaciones. Las librerías que forman la API OpenGL son:

Nombre/Prefijo de las Funciones gl

glu

Archivos Gl.h

Funciones del núcleo de OpenGL.

Opengl32.lib Glu.h Glu32.lib Glaux.h

aux

Descripción

Glaux.dll Glaux.lib

Librería de utilidades más comunes. Totalmente portable. Librería de recursos. Contiene funciones que facilitan tareas como la creación de ventanas independientes de plataforma.

Glut.h glut

Glut32.dll

OpenGL Utility Toolkit. Librería de recursos posterior a la Aux. Añade nuevas prestaciones.

Glut32.lib Tabla 01: Librerías y Ficheros de OpenGL

OpenGL puede operar sobre la superficie de una ventana o bien a pantalla completa, no incorporando función alguna para la gestión de las ventanas. Esto significa que sería preciso recurrir al API del sistema, algo que no entra dentro de la filosofía de OpenGL por el hecho de ser una biblioteca multiplataforma, ya que en Windows habría que usar un conjunto de funciones totalmente distinto que en Unix o Linux para crear y mostrar una ventana, lo cual obligaría al programador a escribir bases de código distintas para cada sistema. La alternativa para evitar esa duplicidad de código es utilizar las bibliotecas Aux o Glut, con funciones que facilitan la gestión de las ventanas de manera independiente al sistema operativo. Consisten en un archivo de cabecera, la biblioteca de importación y la que incorpora el código de las funciones. La librería Aux es un paquete auxiliar para construir aplicaciones de ventanas, además de incluir algunas primitivas geométricas auxiliares. La gran ventaja de este paquete es, al igual que en OpenGL su portabilidad y sencillez.

-1-

Librerías de Recursos: Aux y Glut

La librería Glut es un interfaz de programación para escribir programas OpenGL independientes del sistema de ventanas. Este paquete ha sido implementado por Mark J. Kilgard intentado mejorar la existente Aux y soluciona un hueco en la especificación de OpenGL. Las utilidades que presenta Glut son: múltiples ventanas, uso sencillo de menús y mejora de algunos aspectos ya existentes. De los ejemplos que se han incluido en este tema, algunos incluyen una doble versión, estando desarrollado con la biblioteca Aux y con la biblioteca Glut. Otros ejemplos sólo están desarrollados con una librería. Es muy sencillo saber que librería estamos usando en cada momento ya que OpenGL tiene una notación muy descriptiva, incluyendo el prefijo de la biblioteca a la que pertenecen las funciones, así como el número y tipo de los parámetros de la función. Así las funciones que comienzan por aux pertenecen a la librería Aux y glut a la librería Glut. Entre los ejemplos se encuentra un esqueleto de un programa, un ejemplo de creación de un objeto en 3D y un ejemplo de rotación de una figura (los tres desarrollados tanto con Aux como con Glut). También se incluyen otros ejemplos desarrollados con una de las dos bibliotecas donde se pueden ver más funcionalidades de cada una de ellas.

2

Informática Gráfica

De la Peña, De la Viuda y Sánchez

2.

Registro de Funciones Callback

Las librerías Aux y Glut están diseñadas con un motor dirigido por eventos. Existe un bucle infinito que comienza después de la inicialización y procesa todos los eventos declarados al inicio. Estos pueden ser un botón del ratón que se ha pulsado, una ventana que se cierra, se redimensiona, un cursor que se mueve, unas teclas que se han pulsado, etc. Se deben registrar cada uno de los eventos que se pueden dar en una de las variables de estado de la librería para que el bucle de proceso de eventos compruebe periódicamente si dicho evento ha sido lanzado por alguna acción del usuario. Para registrar un evento utilizaremos rutinas de registro callback que se pasarán como argumento a un conjunto de funciones. Dichas funciones tienen la sintaxis aux/glut[algunEvento]Func, por ejemplo para el click del ratón será auxMouseFunc() ó glutMouseFunc(). Un registro de una función callback para un evento concreto le dice a la máquina de estados que función definida por el usuario se debe llamar si el correspondiente evento es activado. Si se escribe una rutina AccionRaton que especifica qué hacer cuando se pulsa el botón izquierdo del ratón, o el botón derecho entonces será necesario registrar la función callback después de la inicialización (funciones aux/glutInit) en el main() usando la sentencia aux/glutMouseFunc(AccionRaton);. Después de registrar todos los eventos importantes del programa se debe invocar la rutina de procesado de eventos de la librería, aux/glutMainLoop(). Esta función nunca devuelve el control, se queda esperando indefinidamente por eventos de manera que según sea necesario invocará las funciones callback que hayan sido previamente registradas. Es por ello que la función main() de cualquier aplicación OpenGL debe terminar con una sentencia aux/glutMainLoop().

Informática Gráfica

3

Librerías de Recursos: Aux y Glut

4

Informática Gráfica

De la Peña, De la Viuda y Sánchez

3.

La librería AUX de OpenGL

3.1. Introducción La librería Aux es un paquete auxiliar para construir aplicaciones de ventanas, además de incluir algunas primitivas geométricas auxiliares. La gran ventaja de este paquete es además de simplificar mucho el código fuente del programa, que el mismo código nos servirá tanto en Windows como en otras plataformas. Fue creada para facilitar el aprendizaje y escritura de programas en OpenGL sin perderse con las particularidades de un entorno concreto. Aux también implementa funciones para permitir operaciones específicas del sistema, como el intercambio de buffers, la apertura de imágenes y contiene funciones para el dibujo de algunos objetos 3D relativamente simples como esferas, cubos, toros, etc.

3.2. Funciones de la librería AUX Aux posee funciones para la inicialización, manejo de ventanas, procesado de eventos, gestión de la actividad de teclado y ratón y soporte para algunos objetos predefinidos. Todas estas características son compartidas con Glut, siendo ésta última considerablemente más completa.

3.2.1 Inicialización A diferencia de Glut, la librería Aux no necesita una función específica de inicialización para empezar a funcionar. Sí tiene una serie de rutinas que comienzan con el prefijo auxInit que definen las características de la ventana en la que se va a trabajar:

void APIENTRY auxInitDisplayMode(GLenum); Inicializa el modo de visualización de la ventana (tipo de buffer y modo de color). Las opciones de visualización que permite establecer esta función son las siguientes: Valor

Significado

AUX_SINGLE

Especifica una ventana con buffer simple

AUX_DOUBLE

Especifica una ventana con buffer doble

AUX_RGBA

Especifica una ventana en modo RGBA

AUX_INDEX

Especifica una ventana en modo color indexado

AUX_DEPTH

Especifica un buffer de 32 bits de profundidad

AUX_DEPTH16

Especifica un buffer de 16 bits de profundidad

AUX_STENCIL

Especifica un buffer

AUX_ACCUM

Especifica un buffer de acumulación

Informática Gráfica

5

Librerías de Recursos: Aux y Glut

AUX_ALPHA

Especifica un buffer alfa

AUX_FIXED_332_PAL

Especifica una paleta fija 3-3-2 para la ventana

Tabla 02: Valores para las características de ventana

void APIENTRY auxInitPosition(int, int, int, int); Define la posición y tamaño de la ventana. GLenum APIENTRY auxInitWindow(LPCSTR); Muestra la ventana generada. A continuación un ejemplo que ilustre lo anterior: (incluye algunas funcionalidades que se detallarán a continuación en este mismo apartado)

Figura 01: Ejemplo de inicialización en Aux

3.2.2 Manejo de ventanas Creación A la hora de dibujar una ventana en nuestra aplicación hay que tener en cuenta la posición, el tamaño que va a ocupar en la pantalla y el título que le queremos dar. Para todo esto se usan las funciones introducidas en el apartado anterior. La función auxInitPosition(), permite seleccionar el tamaño y la posición de la ventana que se cree a continuación. Recibe cuatro argumentos, los dos primeros (x e y) indican las coordenadas donde se situará la esquina superior izquierda de la ventana, tomando como referencia la esquina superior izquierda del monitor. Y los dos siguientes el ancho y el alto de la

6

Informática Gráfica

De la Peña, De la Viuda y Sánchez

ventana. Se debe tener en cuenta la resolución de configuración de la pantalla, ya que estos parámetros son contados en píxeles. La siguiente llamada debe realizarse a la función auxInitWindow(), que crea físicamente la ventana sobre la pantalla. Se le pasa un único argumento que es el título de la ventana. Después de invocar a esta función, por si se deseara manejar la ventana de alguna forma específica proporcionada por otra librería o dependiente del sistema operativo, se podrían utilizar las siguientes funciones para obtener su manejador: /* hwnd, hdc, and hglrc validos despues de auxInitWindow( )*/ HWND

APIENTRY auxGetHWND(void);

HDC

APIENTRY auxGetHDC(void);

HGLRC APIENTRY auxGetHGLRC(void);

Borrado de la ventana Una vez se tiene creada la ventana en pantalla ya se dispone de un espacio físico para dibujar. OpenGL ofrece una gran variedad de funciones de primitivas geométricas, de hecho, las rutinas de este apartado no pertenecen a Aux pero son fundamentales para la gestión y manejo de ventanas.

La función glClearColor() selecciona los valores de color y alfa para borrar los buffers de color. Su uso combinado con glClear()permite establecer un color de fondo para la ventana o borrar el contenido de la misma sobrescribiéndola de un solo color. El primer parámetro es la componente roja de color de relleno, el segundo la verde, el tercero la azul y el cuarto la componente alfa (nivel de transparencia u opacidad). En OpenGL los colores se representan como una mezcla de rojo, verde y azul, el valor para cada componente del color es un número decimal que oscila entre 0 y 1. Este valor se corresponde internamente al más cercano de los existentes en el hardware de video y la paleta del sistema operativo que se tenga instalada. La cantidad de tonos que permite OpenGL sólo está limitada por el hardware. La componente alfa se usa para efectos especiales. // Establece el buffer de color a amarillo glClearColor(1.0f, 1.0f, 0.0f, 1.0f); Con la función anterior únicamente se ha establecido el color con el queremos limpiar la pantalla pero todavía no se aprecian resultados. Se ha mencionado que OpenGL trabaja con buffers, y esta función limpia un buffer en particular o una combinación de ellos según se le pase por argumentos.

Carga de imágenes Esta librería propone como funciones de carga de imágenes en OpenGL las siguientes:: AUX_RGBImageRec * APIENTRY auxRGBImageLoad(LPCSTR); AUX_RGBImageRec * APIENTRY auxDIBImageLoad(LPCSTR);

Informática Gráfica

7

Librerías de Recursos: Aux y Glut

Donde AUX_RGBImageRec se define como: /* RGB Image Structure*/ typedef struct _AUX_RGBImageRec { GLint sizeX, sizeY; unsigned char *data; } AUX_RGBImageRec;

Ambas reciben como argumento una cadena con el nombre de la imagen. No son muy utilizadas ya que hay otras librerías creadas, mucho más eficaces en la carga de imágenes en OpenGL.

Cerrado y destrucción Como funciones de cerrado explícito de la ventana y salida del programa la librería Aux cuenta con las funciones: void APIENTRY auxCloseWindow(void); void APIENTRY auxQuit(void);

3.2.3 Proceso de eventos El bucle principal de visualización La tarea interactiva más simple que implementa la librería auxiliar de OpenGL es permitir que se controle la ejecución de la aplicación gráfica mediante un bucle principal de visualización, que mantiene la ventana en pantalla hasta que el usuario pulse la tecla <Escape>. El bucle principal de visualización espera a que se produzcan eventos de usuario (mover o cambiar el tamaño de una ventana, pulsar un botón del ratón o pulsar una tecla), y cada vez que se produce un evento, lo atiende y ejecuta una rutina “display” encargada de redibujar los objetos en la escena. El formato de la orden es: void auxMainLoop(void (*displayFunc)(void));

void APIENTRY auxMainLoop(AUXMAINPROC); auxMainLoop se puede considerar una de las funciones principales de cualquier aplicación OpenGL que utilice la librería aux, ya que es la encargada de mantener el programa en funcionamiento hasta que se cierra la ventana y finaliza. Se le pasa un solo argumento que será la función que deba invocar la primera vez que se muestre la ventana y cada vez que esta tenga que ser redibujada.

void APIENTRY auxIdleFunc(AUXIDLEPROC); Otra de las funciones que proporciona Aux es auxIdleFunc() que permite especificar la función de rellamada que se ejecutará cuando no haya otra actividad pendiente o el

8

Informática Gráfica

De la Peña, De la Viuda y Sánchez

programa permanezca ocioso. Su uso junto con la función anterior permite realizar animaciones simples. Se le pasa una función Callback como argumento. Para deshabilitar la ejecución del proceso ocioso se le pasa NULL como argumento. La función glFlush(), de la librería GL, permite gestionar la cola de instrucciones del programa. Su invocación consigue que se ejecuten las sentencias OpenGL que se encuentran en la cola esperando. El funcionamiento interno de OpenGL utiliza un canal de generación de imágenes con procesamiento secuencial. Las sentencias del programa OpenGL se almacenan en una cola hasta que el servidor OpenGL puede procesarlas. En dibujos muy complejos esto supone una gran mejora de prestaciones.

Eventos de ventana, teclado y ratón El bucle principal de visualización implementado por la rutina auxMainLoop mantiene a OpenGL en un ciclo de espera de eventos. Cuando se produce un evento para el que se ha programado una rutina de servicio, OpenGL realiza la siguiente secuencia de acciones: Ejecutar la rutina de servicio asociada al evento. Habitualmente, esta rutina realiza operaciones que afectan al dibujo en pantalla. Ejecutar la rutina display para redibujar la pantalla (según la versión de la librería).

Los posibles eventos que puede atender OpenGL se dividen en tres grupos: Eventos de ventana. Se generan al crear la ventana de la aplicación, cambiar su tamaño o su posición en la pantalla. Los eventos de ventana se atienden mediante la orden auxReshapeFunc de la librería auxiliar de OpenGL. Eventos de teclado. Se generan al pulsar alguna de las teclas siguientes: ‘A’ ... ‘Z’, ‘a’ ... ‘z’, ‘0’ .. ‘9’, ‘←’, ‘↑’, ‘→’, ‘↓’, <Escape>, <Space>, . Los eventos de teclado se atienden mediante la orden auxKeyFunc de la librería auxiliar de OpenGL. Eventos de ratón. Se generan al pulsar o liberar los botones del ratón, y se atienden mediante la orden auxMouseFunc de la librería auxiliar de OpenGL.

Eventos de ventana La orden auxReshapeFunc de la librería AUX especifica la rutina de servicio a ejecutar siempre que la ventana de la aplicación se cambie de tamaño, de posición, o sea expuesta después de estar total o parcialmente oculta. El formato de la orden es el siguiente: void auxReshapeFunc(void (*function)(GLsizei, GLsizei)); El argumento function es un puntero a la función que actúa como rutina de servicio. Esta función espera dos parámetros, la nueva anchura y altura de la ventana. Típicamente, la rutina de servicio establecerá la proyección a utilizar y el marco sobre la ventana para que se ajusten a las nuevas dimensiones manteniendo la proporcionalidad. Los eventos de ventana se utilizarán en la siguiente práctica asociados a la definición de una vista.

Eventos de teclado

Informática Gráfica

9

Librerías de Recursos: Aux y Glut

La orden auxKeyFunc de la librería AUX especifica la rutina de servicio a ejecutar cada vez que se pulsa una de las teclas incluidas en el conjunto de teclas manejables descrito anteriormente. El formato de la orden es el siguiente: void auxKeyFunc(GLint key, void (*function)(void)); El argumento function es un puntero a la función que actúa como rutina de servicio, definida sin parámetros. Esta función se ejecutará cuando se pulse la tecla especificada por el argumento key. Para indicar la tecla utilizaremos las constantes predefinidas al efecto en glaux.h que se verán mas adelante. Los eventos de teclado se suelen utilizar para aplicar transformaciones a un objeto o modificar los parámetros característicos de la vista definida.

Eventos de ratón La orden auxMouseFunc de la librería AUX especifica la rutina de servicio a ejecutar cada vez que se pulse o se libere uno de los botones del ratón. El formato de la orden es el siguiente: void auxMouseFunc(GLint button, GLint mode, void (*function)(AUX_EVENTREC *)); La rutina de servicio function se ejecutará cuando el botón especificado por el argumento button entre en el modo especificado por el argumento mode. Por ejemplo, para asociar la función rutina1 a la pulsación del botón izquierdo del ratón utilizaríamos la orden OpenGL: auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSEDOWN, rutina1);

3.2.4 Uso del teclado y del ratón En cualquier aplicación actual es imprescindible que exista algún tipo de interacción con el usuario, puesto que en ocasiones se pretenderá que el usuario pueda comunicarse con la aplicación y esta responda de acuerdo a las peticiones realizadas. Las dos formas más comunes de comunicación van a ser el teclado y el ratón. En OpenGL mediante el teclado podemos asociar la pulsación una tecla o un conjunto de teclas a una acción concreta, como cambiar de color el dibujo. Con el ratón existen menos posibilidades, podemos definir acciones para cada botón del ratón (izquierdo, derecho y centro) y para la pulsación o cuando se libera. Interacción con el teclado void APIENTRY auxKeyFunc(int, AUXKEYPROC); Recibe el código asociado a la tecla deseada y una función Callback que establecerá la función a llevar a cabo cuando la tecla sea pulsada. OpenGL tiene definidas una serie de constantes para las distintas teclas:

#define AUX_RETURN 0x0D #define AUX_L

10

'L' #define AUX_d

'd'

#define AUX_v

'v'

Informática Gráfica

De la Peña, De la Viuda y Sánchez

#define AUX_ESCAPE 0x1B #defineAUX_M

'M' #define AUX_e

'e'

#define AUX_w 'w'

#define AUX_SPACE

0x20 #define AUX_N

'N' #define AUX_f

'f'

#define AUX_x

'x'

#define AUX_LEFT

0x25 #define AUX_O

'O' #define AUX_g

'g'

#define AUX_y

'y'

#define AUX_UP

0x26 #define AUX_P

'P' #define AUX_h

'h'

#define AUX_z

'z'

#define AUX_RIGHT

0x27 #define AUX_Q

'Q' #define AUX_i

'i'

#define AUX_0

'0'

#define AUX_DOWN

0x28 #define AUX_R

'R' #define AUX_j

'j'

#define AUX_1

'1'

#define AUX_A

'A' #define AUX_S

'S' #define AUX_k

'k' #define AUX_2

'2'

#define AUX_B

'B'

#define AUX_T

'T' #define AUX_l

'l'

#define AUX_3

'3'

#define AUX_C

'C'

#define AUX_U

'U' #define AUX_m

'm' #define AUX_4

'4'

#define AUX_D

'D' #define AUX_V

'V' #define AUX_n

'n' #define AUX_5

'5'

#define AUX_E

'E'

#define AUX_W

'W' #define AUX_o

'o' #define AUX_6

'6'

#define AUX_F

'F'

#define AUX_X

'X' #define AUX_p

'p' #define AUX_7

'7'

#define AUX_G

'G' #define AUX_Y

'Y' #define AUX_q

'q' #define AUX_8

'8'

#define AUX_H

'H' #define AUX_Z

'Z' #define AUX_r

'r'

'9'

#define AUX_I

'I'

#define AUX_a

'a' #define AUX_s

's'

#define AUX_J

'J'

#define AUX_b

'b' #define AUX_t

't'

#define AUX_K

'K'

#define AUX_c

'c' #define AUX_u

'u'

#define AUX_9

Tabla 03: Constantes Teclado OpenGL

Ejemplo del código que se debe insertar en el main de la aplicación para usar las teclas de desplazamiento: // Asociar funciones de movimiento para las teclas W,S,A,D auxKeyFunc(AUX_a, accionIzquierda); auxKeyFunc(AUX_d, accionDerecha); auxKeyFunc(AUX_w, accionArriba); auxKeyFunc(AUX_s, accionAbajo);

Otro ejemplo, para asociar la función rutina1 a la pulsación de la tecla auxKeyFunc(AUX_RETURN, rutina1);

Informática Gráfica

11

Librerías de Recursos: Aux y Glut

Interacción con el ratón void APIENTRY auxMouseFunc(int, int, AUXMOUSEPROC); Recibe tres argumentos: 1º) Botón con el que se desea asociar una función (para ratón de 3 botones) #define AUX_LEFTBUTTON

1

#define AUX_RIGHTBUTTON

2

#define AUX_MIDDLEBUTTON

4

2º) Cuando se debe realizar la acción asociada (al pulsar o al liberar el botón) #define AUX_MOUSEDOWN

16

#define AUX_MOUSEUP

32

3º) Función Callback que define la acción asociada al evento Del tipo: void CALLBACK accionRaton(AUX_EVENTREC *evento); Dicha función espera un argumento que es un puntero a una estructura de datos AUX_EVENTREC. Definida en el fichero de cabecera glaux.h como: typedef struct _AUX_EVENTREC { GLint event; GLint data[4]; } AUX_EVENTREC;

Que contiene la información de: Tipo de evento: /* ToolKit Event Types */ #define AUX_EXPOSE

1

#define AUX_CONFIG

2

#define AUX_DRAW

4

#define AUX_KEYEVENT

8

#define AUX_MOUSEDOWN

16 //Botón abajo

#define AUX_MOUSEUP

32 //Botón arriba

#define AUX_MOUSELOC

64 //Arrastrar con botón pulsado

//Evento de teclado

Indices de data[4] para conocer la posición y estado del ratón: /*

Toolkit Event Data Indices */

//Para eventos de ventana #define AUX_WINDOWX

12

0

Informática Gráfica

De la Peña, De la Viuda y Sánchez

#define AUX_WINDOWY

1

// Para eventos de ratón #define AUX_MOUSEX

0

#define AUX_MOUSEY

1

#define AUX_MOUSESTATUS

3

// Para eventos de teclado #define AUX_KEY

0

#define AUX_KEYSTATUS

1

En esta estructura se almacenan los parámetros característicos del evento, fundamentalmente las coordenadas de ventana dónde se encontraba el cursor en el momento de pulsar o liberar el botón. Para utilizar estas coordenadas, se debería definir function de una forma similar a la siguiente: void {

function(AUX_EVENTREC *event) GLint x, y ; x = event->data[AUX_MOUSEX]; y = event->data[AUX_MOUSEY]; . . .

}

3.2.5 Objetos predefinidos OpenGL es una librería de visualización de polígonos. Es posible, por tanto, construir los modelos a visualizar especificando manualmente los distintos polígonos que los componen; sin embargo, esta tarea resulta tediosa y es relativamente fácil cometer errores. Para facilitar la construcción de modelos a partir de primitivas simples, la librería Aux incluye ordenes para el dibujo de esferas, cilindros, conos, etc. A continuación se listan las funciones que implementan el dibujo de primitivas en Aux: void APIENTRY auxWireSphere(Gldouble radio); void APIENTRY auxWireCube(Gldouble tamaño); void APIENTRY auxWireBox(Gldouble ancho, Gldouble alto, Gldouble profundo); void APIENTRY auxWireTorus(Gldouble radioInterior, Gldouble radioExterior); void APIENTRY auxWireCylinder(Gldouble radio, Gldouble altura); void APIENTRY auxWireIcosahedron(Gldouble radio); void APIENTRY auxWireOctahedron(Gldouble radio); void APIENTRY auxWireTetrahedron(Gldouble radio); void APIENTRY auxWireDodecahedron(GLdouble);

Informática Gráfica

13

Librerías de Recursos: Aux y Glut

void APIENTRY auxWireCone(Gldouble radio, Gldouble altura); void APIENTRY auxWireTeapot(Gldouble tamaño);

Estas rutinas dibujan las distintas primitivas en modo alámbrico, igualmente existen otras similares para el dibujo en modo sólido: void APIENTRY auxSolidSphere(GLdouble); void APIENTRY auxSolidCube(GLdouble); void APIENTRY auxSolidBox(GLdouble, GLdouble, GLdouble); void APIENTRY auxSolidTorus(GLdouble, GLdouble); void APIENTRY auxSolidCylinder(GLdouble, GLdouble); void APIENTRY auxSolidIcosahedron(GLdouble); void APIENTRY auxSolidOctahedron(GLdouble); void APIENTRY auxSolidTetrahedron(GLdouble); void APIENTRY auxSolidDodecahedron(GLdouble); void APIENTRY auxSolidCone(GLdouble, GLdouble); void APIENTRY auxSolidTeapot(GLdouble);

Todas las primitivas se encuentran centradas en el origen, y cuando los parámetros de las órdenes son todos 1.0, todas ellas encajan en una caja con todas sus coordenadas entre -1 y 1. No obstante, pueden utilizarse distintos valores en los parámetros para escalar las primitivas. Por ejemplo, para dibujar un cono de radio 25.0 y altura 40.0 bastaría: auxWireCone(25.0, 40.0);

14

Informática Gráfica

De la Peña, De la Viuda y Sánchez

4.

La librería Glut de OpenGL

4.1. Introducción Para hacer OpenGL verdaderamente portable e independiente de la plataforma fue necesario sacrificar los comandos que interactuaban con el sistema de ventanas (como abrir, cerrar, escalar o dar forma a una ventana, leer la posición del cursor,…) y también con los dispositivos de entrada (como la lectura del teclado, etc). Todas estas acciones son altamente dependientes del sistema operativo. Originalmente, la biblioteca GL tenía su propio conjunto de comandos para manejo de ventanas y periféricos pero eran específicos de IRIX (el SO UNIX de SGI). Se dejaba al desarrollador de OpenGL conocer su propia plataforma y tomar medidas para manejar ventanas en la plataforma nativa. Hasta que Mark J. Kilgard escribió la GLUT-library, un conjunto de herramientas y utilidades de OpenGL que sustituyen a la biblioteca AUX. GLUT, OpenGL Utility Toolkit (no confundir con GLU, OpenGL Utility Library), desarrolla un interfaz de programación con bindings para ANSI C y FORTRAN, para escribir programas OpenGL independientes del sistema de ventanas. Junto con AUX cubre el gran agujero dejado por la especificación de OpenGL. Gracias a GLUT, los desarrolladores pueden usar un interfaz común para el sistema de ventanas independientemente de la plataforma empleada. Las aplicaciones de OpenGL que usan GLUT se pueden portar fácilmente entre plataformas sin tener que introducir muchos cambios en el código fuente. En resumen, GLUT simplifica la producción de código OpenGL y complementa dicha biblioteca. Además, tiene mayor funcionalidad para la manipulación interactiva de objetos 3D. Ofrece, entre otras cosas, las siguientes prestaciones: Ventanas múltiples para render Procesamiento de eventos de entrada iniciados por el usuario (callbacks). Variados dispositivos de entrada. Menús desplegables. Rutinas para generar objetos estándar. GLUT es una librería relativamente pequeña y fácil de aprender. Está bien diseñada siguiendo los pasos de su predecesora AUX. Su API es una máquina de estados, como OpenGL. Esto significa que GLUT tiene una serie de variables de estado que duran toda la ejecución de la aplicación. El estado inicial de la máquina de GLUT se ha elegido razonablemente para ajustarse a la mayor parte de aplicaciones. El programa puede modificar los valores de las variables de estado para ajustarlas a su gusto. Cuando se llama a una función de GLUT, su acción se modifica de acuerdo a los valores de las variables de estado. Las funciones de GLUT son simples, tienen pocos parámetros. Nunca devuelven punteros, y los únicos punteros pasados a las funciones de GLUT son punteros a cadenas de caracteres y manejadores de fuentes.

Informática Gráfica

15

Librerías de Recursos: Aux y Glut

Figura 02: Máquina de estados de la biblioteca GLUT

Las funciones de GLUT se pueden clasificar en varias subAPIs según su funcionalidad: Inicialización Inicio del procesado de eventos Control de ventanas Control de overlay Control de menús Registro de funciones Callback Control del mapa de colores Obtención del estado Trazado de fuentes Trazado de formas geométricas En los siguientes apartados, se explican algunas de las funcionalidades de esta biblioteca.

4.2. Funciones de la librería Glut 4.2.1 Inicialización Todo programa OpenGL que utilice la biblioteca GLUT debe empezar inicializando el estado de la máquina de estados de GLUT. La manera de hacer esto es muy similar a la de la biblioteca AUX, aunque a diferencia de ésta, hay una nueva función, glutInit(), que inicializa el valor de la máquina de estados. Dicha función recibe dos parámetros: argcp y argv.

16

Informática Gráfica

De la Peña, De la Viuda y Sánchez

Argcp es un puntero a la variable argc de la función main() (sin modificar). Al acabar la función, el valor apuntado por argcp se actualiza, ya que glutInit() extrae todas las opciones de la línea de comandos relevantes para la librería GLUT. Argv es la variable argv de la función main() (sin modificar). GlutInit() se encarga de modificar las variables de estado de GLUT y negociar una sesión con el sistema de ventanas. Pocas funciones pueden preceder a glutInit(), sólo el resto de funciones de inicialización de GLUT, aquellas que tienen el prefijo glutInit, y que se pueden usar para establecer los estados de inicialización por defecto. glutInitWindowPosition(int x, int **y) Establece la posición de la ventana en la pantalla. Recibe dos parámetros que son las coordenadas en píxeles de la esquina superior izquierda de la ventana. glutInitWindowSize(int ancho, int **alto) Establece el tamaño de la ventana. Se le pasan dos argumentos que son el ancho y alto en píxels de la ventana. glutInitDisplayMode(unsigned int mode) Inicializa el modo de visualización. Se le pasa un único argumento que el modo de visualizacion o un OR de los posibles valores de visualización, que se muestran en la siguiente tabla:

Opción

Significado

GLUT_RGBA

Selecciona una ventana en modo RGBA. Es el valor por defecto si no se indican ni GLUT_RGBA ni GLUT_INDEX

GLUT_RGB

Lo mismo que GLUT_RGBA

GLUT_INDEX

Seleciona una ventana en modo de índice de colores. Se impone sobre GLUT_RGBA

GLUT_SINGLE

Selecciona una ventana en modo buffer simple. Es el valor por defecto

GLUT_DOUBLE

Selecciona una ventana en modo buffer doble. Se impone sobre GLUT_SINGLE.

GLUT_ACCUM

Selecciona una ventana con un buffer acumulativo

GLUT_ALPHA

Selecciona una ventana con una componente alpha del buffer de color

GLUT_DEPTH

Selecciona una ventana con un buffer de profundidad

GLUT_STENCIL

Selecciona una ventana con un buffer de estarcido

GLUT_MULTISAMPLE

Selecciona una ventana con soporte multimuestra

GLUT_STEREO

Selecciona una ventana estéreo

GLUT_LUMINANCE

Selecciona una ventana con un modelo de color de "luminancia". Tabla 04: Constantes de visualización

Informática Gráfica

17

Librerías de Recursos: Aux y Glut

Se muestra a continuación un ejemplo de inicialización para un programa de animación. Se puede observar que el display se inicializa en modo de doble buffer, ideal para animaciones ya que elimina el parpadeo cuando cambia la imagen en la secuencia de animación.

Figura 03: Ejemplo de inicialización en GLUT

4.2.2 Manejo de ventanas Como su nombre indica, éste subAPI se ocupa de tareas relacionadas con las ventanas usadas por una aplicación OpenGL: crear, cerrar, minimizar una ventana; poner delante, detrás esconder, mover; y poner títulos, posiciones, etc... GLUT permite la creación de dos tipos básicos de ventanas: principal o top-level y subventanas. Ésta es una de las principales novedades de la biblioteca. Ambos tipos soportan operaciones en OpenGL y puede llevar asociadas rutinas Callback. int glutCreateWindow(const char *title); Permite crear una o varias ventanas principales. Se le pasa un argumento que es el nombre de la barra de título. Devuelve un valor entero identificador de la ventana creada ya que en este entorno pueden existir más de una. Los parámetros establecidos en las funciones glutInitWindowPosition() y glutInitWindowSize() afectan únicamente a aquellas ventanas que se definen como top-level. int glutCreateSubWindow(int win, int x, int y, int width, int height) Permite crear una subventana. Los parámetro que se le pasan son, el identificador de la ventana padre, la posición y el tamaño en píxeles de la nueva ventana. También devuelve un valor entero identificador de la ventana. Esta función en vez de crear una nueva ventana en pantalla, utiliza la ya existente para dibujar en ella el contenido de la nueva ventana. Cuando la biblioteca GLUT abre una subventana le proporciona un contexto OpenGL completo e independiente, de forma que cada ventana tiene su propio sistema de coordenadas. El uso de subventanas supone una pérdida de rendimiento para el sistema ya que GLUT refresca el

18

Informática Gráfica

De la Peña, De la Viuda y Sánchez

área de memoria de ventana en pasadas separadas. A continuación se muestra un ejemplo de lo anterior: id_padre=glutCreateWindow("Ventana principal"); glutDisplayFunc(EscenaPrincipal); ... id_hijo = glutCreateSubWindow(id_padre,0,0,600,600); glutSetWindow(id_hijo); glutDisplayFunc(OtraEscena);

Figura 04: Ejemplo de múltiples ventanas y subventanas.

void glutSetWindow(int win) En el caso de trabajar con más de una ventana, el identificador puede ser utilizado como parámetro de esta rutina, que especifica la ventana en la que se va a trabajar y la establece como ventana actual. void glutPostRedisplay(void) Fuerza un evento de exhibición de la ventana, debe ser llamada siempre que un cambio no sea exhibido en pantalla. Las siguientes rutinas completan la lista de funciones soportadas por la gestión de ventanas en GLUT:

Informática Gráfica

19

Librerías de Recursos: Aux y Glut

void glutDestroyWindow(int win) Cierra la ventana cuyo identificador se pasa como parámetro. int glutGetWindow(void) Devuelve el identificador de la ventana actual. void glutSetWindowTitle(const char *title) Establece el texto que se le pasa como parámetro como título de la ventana. void glutSetIconTitle(const char *title) Establece el texto mostrado de la ventana cuando se encuentre minimizada en la barra de tareas. void glutPositionWindow(int x, int y) Modifica la posición de la ventana dentro de la pantalla. void glutIconifyWindow(void) Minimiza la ventana actual. void glutShowWindow(void) Muestra la ventana actual. void glutHideWindow(void) Oculta la ventana actual. void glutFullScreen(void) Maximiza la ventana actual.

4.2.3 Procesado de eventos Las aplicaciones desarrolladas con la librería GLUT se basan en una interfaz de ventanas. Este tipo de interfaces son muy cómodas de usar, pero la programación se complica bastante porque no se puede predecir lo que el usuario va a hacer y en que momento. Como ya se ha dicho antes, GLUT es una máquina de estados. Ahora se verá que también está diseñada como un motor dirigido por eventos. Esto significa que hay un "timer" o bucle continuo que comienza después de la inicialización correspondiente y que procesa uno por uno todos los eventos declarados a GLUT durante la inicialización. Los eventos pueden ser un botón del ratón que se ha pulsado, una ventana que se cierra, una ventana que se redimensiona, un cursor que se mueve, unas teclas del teclado que se han pulsado, un curioso evento "idle" ( esto es, no pasa nada), etc. Cada uno de los posibles eventos se debe registrar en una de las variables de estado de GLUT para que el "timer" o bucle de proceso de eventos de GLUT mire periódicamente si este evento ha sido activado por el usuario. La ejecución de un programa basado en eventos se resume con en el siguiente pseudocódigo:

20

Informática Gráfica

De la Peña, De la Viuda y Sánchez

Figura 05: Pseudocódigo de un programa basado en eventos

Por ejemplo, se puede registrar "pulsar botón del ratón" como un evento para GLUT. Los eventos se registran mediante rutinas de registro callback. Todas tienen la sintaxis glut[algunEvento]Func, en el caso del click del ratón será glutMouseFunc. Un registro de callback le dice a la máquina de GLUT que función definida por el usuario se debe llamar si el correspondiente evento es activado. Así pues, si se escribe una rutina MyMouse que especifica qué hacer cuando se pulsa el botón izquierdo del ratón, o el botón derecho, entonces se registrará esa función callback después de glutInit() en main() usando la sentencia: glutMouseFunc(MyMouse). Después de registrar todos los eventos importantes de una aplicación, se debe invocar la rutina de procesado de eventos de GLUT, glutMainLoop(). Esta función nunca vuelve, el programa básicamente comienza un bucle infinito. Irá llamando, cuando sea necesario, a las funciones callback que hayan sido previamente registradas. Toda función main() de una aplicación OpenGL debe terminar en una sentencia glutMainLoop(). Por defecto, la GLUT tiene definidas funciones callbacks para cada evento posible, pero se puede personalizar este comportamiento según las necesidades. Para hacer esto, algunas de las funciones de las que se dispone son: void glutDisplayFunc( void (*func) (void)) La función func(), que se le pasa como argumento será llamada cada vez que haya que redibujar la ventana. void glutIdleFunc( void (*func) (void)) La función que se le pasa como argumento es llamada cuando no hay entradas del usuario. Cada vez que el procesador de eventos de GLUT da una vuelta al bucle infinito y no encuentra ningún nuevo evento activado. void glutReshapeFunc(void (*func) (int width, int height)) La función func(width, height) se llamará cada vez que la ventana cambie de tamaño, y recibirá como argumentos la nueva anchura y altura. void glutMouseFunc( void (*func) (int button, int state, int x, int y))

Informática Gráfica

21

Librerías de Recursos: Aux y Glut

La función func(button, state, x, y) se llamará cuando se apriete o cuando se suelte el botón definido por el parámetro button en la posición (x,y). Valores de state: GLUT_DOWN

Pulsar con un botón del ratón.

GLUT_UP

Soltar un botón del ratón.

Valores de button: GLUT_LEFT_BUTTON

Botón izquierdo.

GLUT_MIDDLE_BUTTON

Botón del medio.

GLUT_RIGHT_BUTTON

Botón derecho.

void glutMotionFunc(void (*func) (int x, int y)) La función func(x, y) se llamará cuando el ratón se mueva mientras está pulsado uno de sus botones. Esta funcionalidad no estaba implementada en la librería Aux. void glutKeyboardFunc(void (*) unsigned char key, int x, int y) Permite al usuario asociar una acción a la pulsación de una tecla o a un conjunto a de teclas. A continuación un ejemplo, ampliando la plantilla vista para una animación en el apartado 4.2.2:

Figura 06: Ejemplo de registro de eventos en GLUT

22

Informática Gráfica

De la Peña, De la Viuda y Sánchez

4.2.4 Manejo de menús Una de las novedades de esta librería es la creación de menús popup, que no contemplaba la Aux. La GLUT posee un conjunto de rutinas que permiten de una manera sencilla definir y usar menús en cualquier aplicación. int glutCreateMenu(void (*func) (int value) Esta función crea un menú (todavía sin opciones), y le asigna la función func(value). Esta función se llamará cada vez que una de las opciones del menú sea seleccionada por el usuario, y recibirá en value el código identificativo de la opción seleccionada. De esta manera, podremos definir que hace cada opción de menú. Devuelve un identificador de menú, que nos servirá cuando tengamos que referirnos a él. void glutSetMenu(int menu) Esta función hace que el menú identificado como menu sea el menú actual. Por defecto, el menú actual es el último que se ha creado. void glutAddMenuEntry(char *name, int value) Añade una opción de menú al menú actual. Esta opción se llamará name y se identificará por el número value. Void glutAddSubMenu(char *name, int menu) Añade una opción de menú que abrirá un submenú (en lugar de ejecutar directamente un comando, como en el caso anterior). La opción se llamará name y el menú que aparecerá será el identificado como menu (ver función glutCreateMenu()) Void glutChangeToMenuEntry (int entry, char *name, int value) Esta función sirve para modificar una opción del menú actual. El parámetro entry nos indica la opción a modificar (por ejemplo, para modificar la primera, entry = 1), name será el nuevo nombre de la opción y value el nuevo identificador que se le pasará a la función controladora de menú. void glutAttachMenu(int button) Esta función hace que el menú actual aparezca cada vez que se pulse el botón del ratón indicado por button (GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON). A continuación se muestra el código necesario para la creación de un sencillo menú:

Informática Gráfica

23

Librerías de Recursos: Aux y Glut

Figura 07: Ejemplo de creación de un menú en GLUT

4.2.5 Fuentes de texto El manejo de fuentes de texto es una de las partes débiles de OpenGL. Su implementación es complicada ya que la biblioteca GL sólo proporciona funciones muy primitivas para trazado de bitmaps que obligan a disponer de una librería propia de bitmaps para los caracteres. GLUT va un poco más allá y dispone de unas pocas funciones que permiten renderizar texto en pantalla.

glutBitmapCharacter(void * font, int character)

Permite escribir texto carácter a carácter pasándole sólo la fuente del texto y el carácter a imprimir. Tipos de fuentes en Glut:

24

o

GLUT_BITMAP_9_BY_15

o

GLUT_BITMAP_8_BY_13

Informática Gráfica

De la Peña, De la Viuda y Sánchez

o

GLUT_BITMAP_TIMES_ROMAN_10

o

GLUT_BITMAP_TIMES_ROMAN_24

o

GLUT_BITMAP_HELVETICA_10

o

GLUT_BITMAP_HELVETICA_12

o

GLUT_BITMAP_HELVETICA_18

Figura 08: Ejemplo de manejo de textos en GLUT

En el ejemplo de ventanas y subventanas se han usado también estas funciones para generar texto en pantalla. Esta es la rutina definida para escribir en pantalla el texto que obtiene como parámetro:

Figura 09: Rutina para escribir en texto en pantalla con GLUT

Informática Gráfica

25

Librerías de Recursos: Aux y Glut

4.2.6 Objetos predefinidos No existen novedades en las rutinas de dibujo implementadas por glut, al igual que aux ofrece dos tipos de dibujos, sólidos o alámbricos: Se dispone de las siguientes funciones: Esferas: glutWireSphere(radius, slices, stacks), glutSolidSphere(radius, slices, stacks) Cubos: glutWireCube(size), glutSolidCube(size) Conos: glutWireCone(base, height, slices, stacks), glutSolidCone(base, height, slices, stacks) Dodecaedros: glutWireDodecahedron(void), glutSolidDodecahedron(void) Octaedros: glutWireOctahedron(void), glutSolidOctahedron(void) Tetraedros: glutWireTetrahedron(void) glutSolidTetrahedron(void) Icosaedros: glutWireIcosahedron(void) glutSolidIcosahedron(void) Teteras: glutWireTeapot(void) glutSolidTeapot(void) Toroides: glutWireTorus(void) glutSolidTorus(void)

26

Informática Gráfica

De la Peña, De la Viuda y Sánchez

5.

Conclusión

A lo largo de todo el tema se ha pretendido dar una visión general de las dos librerías mas importantes de OpenGL para el uso de ventanas que son independientes de plataforma, Aux y Glut. La librería Aux otorga un control total sobre los eventos y para la creación de ventanas. Aux se caracteriza por su sencillez, lo cual no quiere decir que no sea completa. Unos años después de la creación de esta librería se creó Glut, basada completamente en su predecora, cumpliendo por lo tanto sus funciones y añadiéndole algunas más, como la creación de menús, o llamada a subventanas. Características: Característica

AUX

GLUT

Funciones de Inicialización

X

X

Manejo de Ventanas

X

X

Manejo de Subventanas

X

Procesado de Eventos

X

X

Objetos Predefinidos

X

X

Manejo de Menús

X

Tabla 05: Comparación AUX – GLUT

Para concluir resaltar que las dos librerías son igual de válidas, su estructura es similar, por lo que a la hora de diseñar cualquier programa tan solo deberemos basarnos en si vamos a necesitar cualquiera de las opciones que añade Glut. Si no se requieren las funcionalidades extra aportadas por Glut, se puede escoger cualquiera de las dos, aunque lo mas recomendable es usar Glut, ya que la estructura es similar, y se puede continuar utilizando si un día se desea ampliar las funciones de la aplicación.

Informática Gráfica

27

Related Documents

Lecc 3
December 2019 7
Lecc 11
December 2019 18
Lecc 6
December 2019 16
Lecc 12
December 2019 17
Lecc 9
December 2019 15
Lecc 13
December 2019 9

More Documents from "maria"