Ir al Hogar Ver Índice Buscar Enlaces Acerca de nosotros
[LinuxFocus Image]
[Navegation Bar]
  Noticias   Archivos   Compañías   Consejos 

GLUT: Utilizando Menús

por Miguel Angel Sepúveda


Este artículo es el tercero de la serie dedicada a la GL Utility Toolkit (GLUT) escrito por Mark Kilgard. GLUT es una herramienta muy útil para desarrolladores con OpenGL porque abstrae en un API simple de aprender y utilizar la parte dependiente de la arquitectura de la aplicación OpenGL.

Como se ha mencionado en artículos anteriores, las razones por razones de desarrollo OpenGL sólo incluye directivas para la parte independiente de la arquitectura de un API 3D avanzado. Abrir ventanas, manejo de la entrada de teclado, etc.. son muy dependientes de la plataforma y está fuera del alcance de OpenGL. GLUT es la respuesta a este problema: GLUT ofrece un interfaz común para múltiples plataformas para el manejo de cosas como ventanas, buffers, renderización de texto, entrada por el teclado y menús.

Hoy exploraremos el uso de menus dentro de nuestras aplicaciones OpenGL. Un menú es una forma más de comunicación con el usuario por parte de la aplicación. En nuestro artículo previo (Manejo de Ventanas) demostramos otra técnica para la entrada del usuario, teclas rápidas. GLUT captura los eventos de entrada de teclado tan bien como los eventos de ratón y nos deja introducir funciones (callbacks) para manejar estos incidentes. La desventaja de las "teclas rápidas" es que son invisibles, requieren que el usuario lea un manual o recuerde que tecla hace tal cosa. Los menús, por otra parte son mucho más flexibles porque son gráficos y muestran las opciones de usuario disponibles actualmente.

Como ejemplo he aquí el código fuente de un programa ejemplo (../../common/May1998/example1.tar.gz). Este programa es una modificación del programa mostrado en el artículo anterior Manejo de Ventanas. Obtenga el programa y compilelo utilizando el Makefile suministrado.

La compilación requiere la librería OpenGL (Mesa, por ejemplo) y la biblioteca GLUT. Ambas librerías son fácilmente obtenibles y están incluidas de una forma u otra en muchas distribuciones de Linux. Tras la compilación obtenemos el fichero ejecutable, example1 . Ejecútelo y podrá ver una nueva ventana con un triángulo en color de vértices rojo, verde y azul (ver figura de la izquierda).

El área contiene una ventana principal con fondo negro y un triángulo en el centro y una sub-ventana con fondo gris con texto escrito en ella. Nuestro ejemplo es realmente una animación en tiempo real por lo que el campo de tiempo en la sub-ventana debe ser incrementado.

Mueva el ratón al área de la ventana principal, mantenga pulsado el botón izquierdo del ratón. Este evento es manejado por nuestro ejemplo y debe abrir el siguiente menú:

El menú contiene tres opciones (rotar, trasladar, cambiar color) y una final para terminar la aplicación. Mientras mantenga pulsado el botón izquierdo del ratón, muévase a cada opción y pruebe lo que ocurre.

Seleccionando "Rotation On" el triángulo rotará alrededor de su centro de gravedad, la opción "Translation On" moverá el triángulo horizontalmente a través de la ventana y lo ocultará cuando el final de la ventana sea alcanzado. La opción "Change Color" lanzará un sub-menú nuevo con estas nuevas opciones:

  • Red Representa el triángulo en rojo
  • Blue Representa el triángulo en azul
  • Green Representa el triángulo en verde
  • RGB Representa el triángulo en rojo, verde y azul

Este es un ejemplo muy simple del uso de menús en una aplicación OpenGL. La apariencia de menús y sub-menús es dependiente de la plataforma. El aspecto mostrado aquí es el del GLUT para Linux, compilado y ejecutado bajo Windows 95/NT tendrá una apariencia diferente. Lo que importa es que esta funcionalidad es portable si utiliza la librería GLUT.

Note que el menú principal tiene dos tipos diferentes de entradas. El primer tipo (Rotation On, Translation On) cambia cuando la acción es ejecutada. Esto significa que tras lanzar el triángulo en modo de rotación, la próxima vez que vea el menú principal aparecerá "Rotation Off". La otra clase de entrada en el menú permanece siempre constante, como "Change Color", "Red", "Blue" y "Green".

Existen unas algunas cosas interesantes que me gustaría advertir antes de continuar describiendo como programar estos menús. ¿Recuerda que esta demo tiene dos teclas rápidas? (Manejo de Ventanas). Estas teclas son "q" para salir y "i" para activar o desactivar la información. Intente utilizarlas de nuevo, todavía funcionan.

Mientras que el mensaje con información está activado (sub-ventana), mueva el cursor a cualquier lugar dentro de la región gris y pulse el botón izquierdo del ratón. ¡Sorpresa! Verá este otro menú:

Esto demuestra que los menús no sólo son relacionados con eventos (botón izquierdo del menú) sino que son utilizados de acuerdo con el actual contexto OpenGL. También hemos mencionado en nuestro pasado artículo que una sub-ventana GLUT incorpora su propio contexto OpenGL, aquí podemos ver otra consecuencia de este hecho. Dos menús han sido relacionados con el mismo evento pero en diferentes contextos. El desarrollador tiene una herramienta potente para escribir un interfaz de usuario sofisticado para su aplicaciones.

Todavía más interesante es el hecho que si desactiva el mensaje informativo utilizando la tecla "i" y mueve el cursor ala parte superior del área, será incapaz de volver a la entrada "This is a dummy entry". ¿Porque?, porque cuando oculta la sub-ventana el contexto general (incluyendo los menús incorporados) con ocultados también.

A continuación vamos a empezar a describir el contenido del programa. Asumo que el lector está familiarizado con el material GLUT y OpenGL presentado en los artículos previos. El área main() contiene diferentes secciones, ¡el orden es importante!:

  • Inicialización de GLUT. Abre una ventana, pasa argumentos de la línea de comandos, fija el modo de visualización y opciones.
  • Creación de la Ventana Principal. Crea la ventana principal, fija las funciones (callbacks) principales asociadas con la ventana, define la función idle
  • Crear un Sub-menu. Este sub-menú maneja la opción "Change Color", y será incluida dentro del menú principal posteriormente.
  • Crear Menú Principal. Construye el menú principal, añade los ítems y el sub-menú previamente definido, finalmente asocia este menú al botón izquierdo del ratón. Nótese que todavía estamos en el contexto de la ventana principal.
  • Crear lista de "llamadas GL" . Este es un punto avanzado de OpenGL que no trataremos aquí exhaustivamente. Es suficiente con saber que una lista de llamandas es una forma de construir y encapsular objetos OpenGL en tiempo de ejecución para su posterior invocación. Invocando un elemento "GL call list", en oposición a construir el objeto una y otra vez es mucho más eficiente para invocaciones posteriores. En esta demo hay cuatro elementos de este tipo: un triángulo rojo, uno azul, uno verde y uno RGB.
  • Creación de una sub-ventana . Crea una sub-ventana, salva un manejador, asocia las correspondientes funciones. Después que la sub-ventana es creada un nuevo contexto se activa.
  • Creación del Menú Principal para la sub-ventana. Exactamente como hicimos anteriormente, creamos un nuevo menú, añadimos entradas y lo asociamos al botón izquierdo del menú. Ahora, el menú estará asociado al contexto de la sub-ventana.

Excepto para la creación del menú, todas las otras secciones deben ser familiares al lector. Una rápida inspección del código para la creación de menús revela cuan simple es. Los menús son creados por la directiva int glutCreateMenu( void (f*)(int) ) , la función f es de tipo callback que toma el número devuelto por la opción del menú escogida y realiza la acción pertinente. El valor devuelto por la función glutCreateMenu es un identificador entero para la nueva ventana creada.

Las funciones utilizadas para manejo de eventos de menú son muy simples. Examine void mainMenu(int) o void subMenu(int). Básicamente utilizan una sentencia switch que procesa el ítem del menú escogido.

Tras crear el menú nuestro código añade entradas a éste utilizando la función void glutAddMenuEntry(char *s, int nr), donde "s" es el texto a escribir en el campo de la entrada en el menú y "nr" es el identificador de la función a llamar cuando este ítem sea escogido. Obviamente evite utilizar identificadores iguales para entradas diferentes en el mismo menú.

Los Sub-menus son añadidos de una forma similar utilizando la función void glutAddSubMenu(char *s, int nr).

Finalmente, tras completar el menú, es asociado a un evento de entrada (botón izquierdo del ratón) con la función glutAttachMenu. Esta función también puede tomar los valores GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON.

Las entradas en los menús pueden ser cambiadas en cualquier momento gracias al comando void glutChangeToMenuEntry(int entry, char *s, int value), que cambia la entrada en el menú "entry" de la ventana actual por otra que tiene la etiqueta s y devuelve value a la función la invoca. En nuestro ejemplo hemos utilizado

   glutChangeToMenuEntry(2, "Translation On", 2);
para cambiar la entrada número 2 del menú principal, y así para los otros casos.

GLUT permite más posibilidades: cambiar una opción de menú por un sub-menu de tipo cascada y viceversa, destruir menús, eliminar opciones de un menú, y más. No las exploraremos porque pienso que el ejemplo expuesto es suficientemente simple y funcional para satisfacer las necesidades de muchos usuarios. Si necesita capacidades extra por favor consulte el manual más reciente sobre GLUT.


Traducido por Jose M. Laveda Molina

Para más información:
© 1998 Miguel Angel Sepúveda
Páginas web mantenidas por Miguel A Sepúveda.