Вы находитесь на странице: 1из 12

ndice

Introduccin........................................................................................................ 1
Objetivo.............................................................................................................. 1
Marco terico...................................................................................................... 1
Desarrollo............................................................................................................ 6
Conclusiones..................................................................................................... 11
Bibliografa........................................................................................................ 11

Introduccin

Objetivo
Desarrollar una aplicacin con openGL que muestre mediante un men un
tringulo y un cuadrado

Marco terico
Mens en OpenGL

void menu_nivel_2(int identificador){

/* Segn la opcin de 2o nivel activada, ejecutar una rutina u otra */

switch( identificador){
case 0:
ControlVertices( );
break;
case 1:
ControlNormales( );
break;
case 2:
ControlAristas( );
break;
}
}

void menu_nivel_1(int identificador){

/* Segn la opcin de 1er nivel activada, ejecutar una rutina u otra */

switch( identificador){
case 0:
ControlLuces( );
break;
case 1:
ControlColisiones( );
break;
case 2:
ControlSonido( );
break;
case 3:
exit( -1 );
}
}

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

int submenu, id;

/* Definicin de la ventana */

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
id=glutCreateWindow("Ventana con men contextual");

/* Creacin del men */


submenu = glutCreateMenu(menu_nivel_2);

glutAddMenuEntry("Vrtices", 0);
glutAddMenuEntry("Normales", 1);
glutAddMenuEntry("Aristas", 2);
glutCreateMenu(menu_nivel_1);
glutAddSubMenu("Ver", submenu);
glutAddMenuEntry("Luces on/off", 0);
glutAddMenuEntry("Colisiones on/off", 1);
glutAddMenuEntry("Sonido on/off", 2);
glutAddMenuEntry("Salir", 3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
........
........
aqu vendran los callbacks, el Loop, el retorno del entero....lo de siempre!!!
........
........
}

Las rutinas asociadas a cada opcin de men no las defino, claro. Eso ya
dependera de la aplicacin. Tan slo me interesa la pura creacin del men sin
importarme las acciones que se llevan a cabo si se activa, ok?
Yo creo que el cdigo ya se entiende bastante bin de por s pus es muy
lgico. Voy a comentarlo un poco.

Fijaros que con glutCreateMenu, genero un nuevo men y adems le asocio la


rutina que tendr que llamarse cuando este men se active. En el caso del
men de primer nivel se llamar a menu_nivel_1, mientras que el men de
segundo nivel llamar a menu_nivel_2.

Al men de primer nivel le asociamos 5 posibles opciones a activar usando


glutAddMenuEntry. La primera, Ver, desplegar otro men mientras que las
restantes cuatro deben procesarse en menu_nivel_1. Es por eso que a cada
opcin se le asocia un identificador (integer), de manera que en la funcin
menu_nivel_1 se hace una cosa u otra dependiendo de este entero. ste nos
indica que opcin se activ. Lo controlamos con un Switch de ANSI C
(analizador de casos posibles).

Para el men de segundo nivel todo es idntico excepto que se "engancha" al


de primer nivel mediante...

glutAddSubMenu("Ver", submenu);

que le dice al men de primer nivel que la primera de sus opciones se llama
Ver y debe llamar a un men asociado al entero submenu. Mirad que este
entero lo hemos asociado usando:

submenu = glutCreateMenu(menu_nivel_2);

y por supuesto este segundo nivel tambin dispone de sus propias opciones,
creadas de igual manera que antes. Por timo le decimos a GLUT que este
men debe asociarse a pulsar el botn derecho del ratn con:
glutAttachMenu(GLUT_RIGHT_BUTTON);

Un evento es "algo que el usuario puede hacer" como por ejemplo maximizar
una ventana, redimensionarla, pulsar el botn izquierdo del ratn, o usar una
determinada combinacin de teclas. En todos estos casos deberemos "ejecutar
algo de cdigo" dentro de nuestro programa, si es que estaba previsto as. Para
los "ms informticos" dir que se trata de algo as como una interrupcin que
provoca la ejecucin de una determinada rutina cuando se la activa.

En OpenGL, y gracias a GLUT, se le permite al usuario "jugar" pulsando botones


del ratn, movindolo por la pantalla, apretando teclas, cambiando la ventana
de la aplicacin. Cada vez que ste provoque alguno de estos eventos
deberemos llamar a una determinada rutina o funcin para que se haga cargo
de la accin a tomar.

Las ms comunes funciones que OpenGL llama automticamente al detectar


uno de estos eventos son:

glutMouseFunc( funcin de control eventos con el ratn );


glutMotionFunc( funcin de control eventos de movimiento del ratn );
glutReshapeFunc( funcin de control del cambio de tamao de la ventana de
visualizacin );
glutKeyboardFunc( funcin de control eventos con el teclado );
glutDisplayFunc( funcin de control del render );
glutIdleFunc( funcin que se activa cuando no hacemos NADA );
Son las llamadas "Callbacks" o funciones controladoras de eventos.
Analizemos algunos casos:

El ratn
Lo ms normal es querer controlar lo que debe hacerse cuando el usuario pulsa
uno de sus botones. Si definimos lo siguiente en la funcin MAIN de nuestro
programa...
glutMouseFunc( ControlRaton );

OpenGL entiende que cada vez que se pulse uno de los botones del ratn debe
llamar a una rutina llamada ControlRaton, que por supuesto tenemos que crear
y definir nosotros mismos. Lo haremos de esta forma:
void ControlRaton( int button, int state, int x, int y ){
<cdigo que deseemos se ejecute>
}

donde los parmetros que la funcin nos da (automticamente y sin tener que
hacer nada) son los siguientes:

button, un entero que puede tomar los valores GLUT_LEFT_BUTTON,


GLUT_MIDDLE_BUTTON o GLUT_RIGHT_BUTTON segn el usuario haya pulsado
el botn izquierdo, el del medio o el derecho, respectivamente. Estas
constantes estan predefinidas y podemos usarlas sin problema en nuestro
cdigo pues GLUT las interpretar correctamente.

state, puede tomar los valores GLUT_UP o GLUT_DOWN, segn si se ha


pulsado/soltado el correspondiente botn.

X e Y, son las coordenadas referidas a la ventana de visualizacin, no al mundo


virtual, en las que se puls/solt el susodicho botn.

Es importante aclarar que GLUT espera que los parmetros sean stos en el
caso de este callback y no otros !!!

Veamos un ejemplo:

void ControlRaton( int button, int state, int x, int y ){

if (button==GLUT_LEFT_BUTTON && state==GLUT_DOWN){


printf( "Cerramos la aplicacin.../n");
exit(-1);
}

En este caso, cuando el usuario pulse el botn izquierdo del ratn, sacaremos
un mensaje diciendo que se cierra la aplicacin y entonces la cerraremos. La
funcin exit(-1) pertenece a ANSI C, no a OpenGL, y provoca el fin de la
ejecucin.
Lo vis viendo ms claro?

En el caso de la funcin:

glutMotionFunc( ControlMovimientoRaton );

GLUT llamar a ControlMovimientoRaton a intervalos discretos, es decir de


tanto en tanto, mientras el ratn se est moviendo por la pantalla. La
definimos as:

void ControlMovimientoRaton( GLsizei x, GLsizei y ){


<cdigo que deseemos se ejecute>
}

teniendo en cuenta que X e Y son las coordenadas de pantalla por las que el
ratn est pasando. As podramos usar esta funcin para indicar nuestra
situacin en pantalla de la siguiente forma:

void ControlMovimientoRaton( GLsizei x, GLsizei y ){


printf( "La posicin del ratn en coordenadas de ventana es:/n");
printf( " X = %f/n", (GLfloat)GLsizei x);
printf( " Y = %f/n", (GLfloat)GLsizei y);

De manera que mientras movemos el ratn se imprimen estas tres lneas en la


ventana desde la que hemos ejecutado el programa, una ventana de DOS o
UNIX (no en la ventana de visualizacin, esa es para los grficos!!!). Y claro, los
valores de X e Y se irn actualizando segn nos vayamos moviendo ya que se
llamar a ControlMovimientoRaton sucesivamente.

GLsizei es un tipo de variable numrica de OpenGL comparable a un real.


Fijaros en que hago un casting para convertirla en los printf.

Qu os parece?

El teclado
El control del teclado se realiza mediante:
glutKeyboardFunc( ControlTeclado );
esto lo aadimos a nuestra funcin de MAIN y entonces definimos a parte la
funcin de control propiamente dicha:

void ControlTeclado( unsigned char key, int x, int y ){


<cdigo que deseemos se ejecute>
}

Desarrollo
#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

#define SOLID_CUADRADO 2
#define SOLID_TRIANGLE 3
#define EXIT 9
#define ESC 27
#define TAB 9

int opcion = 1;

//Seleccion de la figura a dibujar


void menuAction(int value)
{
opcion = value;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(0.5,0.2,0.9);

switch(value)
{

//Dibuja un cuadrado
case SOLID_CUADRADO:
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glColor3f(0.0,1.3,1.0);
glVertex2d(-0.5, -0.5);
glColor3f(0.5,0.2,0.9);
glVertex2d(-0.5, 0.5);
glColor3f(0.,0.2,0.3);
glVertex2d(0.5, 0.5);
glColor3f(0.6,0.1,0.8);
glVertex2d(0.5, -0.5);
glEnd();
glFlush();
break;
//Dibuja un triangulo
case SOLID_TRIANGLE:
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glColor3f(0.0, 1.0, 1.0);
glVertex2d(-0.5, 0.5);
glColor3f(1.0, 0.0, 1.0);
glVertex2d(0.5, 0.5);
glColor3f(1.0, 0.0, 0.0);
glVertex2d(0.5, -0.5);
glEnd();
glFlush();
break;

case EXIT:
exit(0);
break;
}
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h); // Establecer el tamao del rea visible.
glMatrixMode(GL_PROJECTION); // Modificar la matriz de proyeccin.
glLoadIdentity(); // Inicializar la matriz de proyeccin.
glMatrixMode(GL_MODELVIEW); // Modificar la matriz de vista del modelo.
}

void display(void)
{
glLoadIdentity(); // Inicializar la matriz de vista del modelo.

// Borrar el buffer de color y de profundidad.


glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

menuAction(0);

glutSwapBuffers(); // Intercambiar el buffer de dibujado por el buffer de


despliegue.
glFinish();
}

void menu()
{
int submenu1;
submenu1 = glutCreateMenu(menuAction);//Creamos submennu

glutAddMenuEntry("Dibujar cuadrado",SOLID_CUADRADO);
glutAddMenuEntry("Dibujar triangulo",SOLID_TRIANGLE);

glutCreateMenu(menuAction);
glutAddSubMenu("Figura solida",submenu1);
glutAddMenuEntry("Salir",EXIT);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
//void specialKey(int key, int x, int y)
//{
// if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) // testing SHIFT status
// {
// switch(key)
// {
// case GLUT_KEY_LEFT:
// break;
//
// case GLUT_KEY_RIGHT:
// break;
//
// case GLUT_KEY_UP:
// break;
//
// case GLUT_KEY_DOWN:
// break;
// }
// }
//}
void mouse(int button, int state,int x, int y)
{
switch(button)// Capturamos el evento del boton derecho del raton
{
case GLUT_LEFT_BUTTON:
if(state == GLUT_UP)
{
opcion++;

if(opcion > 8)
{
opcion = 1;
}
menuAction(opcion);
}
break;
}
}
//void keyboard(unsigned char key, int x, int y)
//{
// switch(key)
// {
// case ESC:
//
// exit(0);
// break;
// case TAB:
// opcion++;
// if(opcion > 8)
// {
// opcion = 1;
// }
// menuAction(opcion);
// break;
// }
//}
int main(int argc, char **argv)
{
glutInit(&argc, argv); // Inicializar GLUT
// Inicializar modo de despliegue: usar profundidad, transparencia y double
buffering.
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glutCreateWindow("Menu");
// Crear una ventana con el ttulo indicado.
menu();//Setea el submenu

//glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);//Recibe la funcion mouse para detectar el click
derecho
glutDisplayFunc(display); // Indicar la funcin para desplegar.
glutReshapeFunc(reshape); // Indicar la funcin para cambios de tamao en
la ventana.
glutMainLoop(); // Pasar el control a GLUT.

return 0;
}

Resultados
Conclusiones

Bibliografa