Computación Gráfica
Práctica 1: Plantilla interacción en OpenGL
Jorge Victorino Guzmán
Objetivos
•
Iniciar con un programa plantilla de OpenGL con la librería GLUT y activar todas las
funciones que permitan realizar una interfaz con el usuario.
•
Desarrollar un ejemplo con cada una de las opciones que tiene el usuario para
interactuar con una aplicación gráfica y dejar una plantilla de funciones para todos los
programas a realizar dentro de la materia.
•
Desarrollar una plataforma conceptual base para todas las aplicaciones gráficas a construir.
Requerimientos
Se requiere un IDE del lenguaje C++ para montar todos los programas de la materia. En el
caso del sistema operativo Windows puede consultar en la pagina las instrucciones para
instalar el DevC++ con soporte a la librería GLUT. Para desarrollar aplicaciones en OpenGL.
Actividades:
Descargar y abrir programa blanco.c
Repasar todas las líneas del programa, correr el programa y cambiar el tamaño de la
ventana. Observar la ventana terminal cuando se cambia el tamaño a la ventana del lienzo.
1. Inicialización del lienzo.
//especifica el tamaño inicial de la ventana del lienzo glutInitWindowSize(800, 600);
//especifica la posición de la esquina superior izquierda de la ventana GLUT en píxeles. glutInitWindowPosition (100, 100);
//Crea la ventana con el nombre dado glutCreateWindow("GL Template Basic"); //Usa doblebuffer y modo de color RGBA glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
Funciones que deben ir en un programa OpenGL:
//función para iniciar la librería glut y pasar los parametros de la consola glutInit(&argc, argv);
//CALLBACK de despliegue, apuntador a función de renderizado glutDisplayFunc(display);
// CALLBACK acción de redimensionamiento de la pantalla glutReshapeFunc(resize);
//función de inicialización init();
//Esta función arranca a correr la librería glut
glutMainLoop();
Para manejo del color es posible utilizar un arreglo de 3 posiciones de valores enteros sin
signo de 8 bits, de la siguiente manera:
los tres elementos de esta estructura corresponden a la intensidad de los canales rojo, verde
y azul en el intervalo de 0 a 255.
2. Activar la funcionalidad del ratón:
Agregar CALLBACK captura el movimiento pasivo del ratón (agregar en la función main()
después del CALLBACK resize):
glutPassiveMotionFunc(mouse_move);
Utilizar variables globales para determinar las posiciones del ratón: xt, yt guardan la posición
actual, xi, yi guardan la posición inicial al hacer clic y xf, yf guardan la posición final cuando
hay arrastre del puntero:
int xi, xf, xt; int yi, yf, yt;
//definir la funcionalidad del ratón. void mouse_move(int x, int y)
{
// captura la posición del puntero todo el tiempo xt = x;
yt = windowHeight – y; // manda a pintar la escena glutPostRedisplay(); }
Agregar CALLBACK en la función main para activar la captura del evento de presionar o
liberar un botón del ratón.
glutMouseFunc(mouse_click);
La función tiene los parámetros: botón, estado y la posición, con las siguientes opciones:
button: = { GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON} state: = { GLUT_UP, GLUT_DOWN}
Definir la funcionalidad del click
// Captura el evento de click
void mouse_click(int button, int state, int x, int y) {
Color c;
if(state == GLUT_DOWN){
// captura posicion inicial de arrastre xi = x;
yi = windowHeight y; xf = xi;
yf = yi;
//captura el color del pixel sobre puntero y lo imprime //glReadPixels(xi, yi, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, c); getPixel(xi, yi, c);
printf("Posicion inicial: %d, %d, color(%3d,%3d,%3d)\n", xi, yi, c[0], c[1], c[2]);
}
if(state == GLUT_UP){
// captura posicion inicial de arrastre
}
// manda a pintar (metodo display) glutPostRedisplay();
}
Activar la funcionalidad de arrastre del ratón en la función main:
glutMotionFunc(mouse_drag);
La posición inicial del evento de arrastre depende del evento presionar y se debe guardar en
una variable global para poderla utilizar en cualquier otra función. A continuación se muestra
un ejemplo que define la funcionalidad del arrastre:
void mouse_drag(int x, int y) {
xf = x;
yf = windowHeight y;
// manda a pintar (metodo display) glutPostRedisplay();
}
Activar la funcionalidad del teclado en la función main:
Existen en total 4 funciones que se pueden activar en la GLUT para usar el teclado,
dependiendo de si la tecla se presiona o se libera o si son teclas especiales o no:
glutKeyboardFunc(normal_key); glutKeyboardUpFunc(normal_keyUp); glutSpecialFunc(special_key); glutSpecialUpFunc(special_keyUp);
Ejemplos de definición de las funciones de presionar teclas:
// Captura del teclado, teclas normales void normal_key(GLubyte key, int x, int y) {
// termina el programa con la tecla ESC printf("normal key: '%c' \n", key); if(key == 27)
exit(0); }
Existen macros en la GLUT para referirse a las teclas especiales:
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
En este ejemplo se muestra como se pueden usar las macros:
void special_key(int key, int x, int y) {
switch(key){
case GLUT_KEY_F1: printf(“presionó: F1\n”); break; case GLUT_KEY_F2: printf(“presionó: F2\n”); break; case GLUT_KEY_F3: printf(“presionó: F3\n”); break; case GLUT_KEY_F4: printf(“presionó: F4\n”); break; case GLUT_KEY_F5: printf(“presionó: F5\n”); break; case GLUT_KEY_F6: printf(“presionó: F6\n”); break; case GLUT_KEY_F7: printf(“presionó: F7\n”); break; case GLUT_KEY_F8: printf(“presionó: F8\n”); break; case GLUT_KEY_F9: printf(“presionó: F9\n”); break; case GLUT_KEY_F10: printf(“presionó: F10\n”); break; case GLUT_KEY_F11: printf(“presionó: F11\n”); break; case GLUT_KEY_F12: printf(“presionó: F12\n”); break;
case GLUT_KEY_LEFT: printf(“presionó: Flecha Izquierda\n”); break; case GLUT_KEY_UP: printf(“presionó: Flecha Arriba\n”); break; case GLUT_KEY_RIGHT: printf(“presionó: Flecha Derecha\n”); break; case GLUT_KEY_DOWN: printf(“presionó: Flecha Abajo\n”); break; case GLUT_KEY_PAGE_UP: printf(“presionó: Página Arriba\n”); break; case GLUT_KEY_PAGE_DOWN: printf(“presionó: Página Abajo\n”); break; case GLUT_KEY_HOME: printf(“presionó: Inicio\n”); break;
case GLUT_KEY_END: printf(“presionó: Fin\n”); break;
case GLUT_KEY_INSERT: printf(“presionó: Insertar\n”); break; default: printf(“presionó la tecla número: %d\n”, key); }
}
Por medio de la interacción del usuario con el programa se capturan y configuran valores
diferentes en variables globales que son consultados por la función de despliegue. De esta
forma se mantiene el control de visualización por medio de una única función que se encarga
de pintar toda la escena.
// Funcion principal de despliegue void display(void)
{
int i;
// limpia la pantalla
glClear(GL_COLOR_BUFFER_BIT);
// Pinta rectangulo gris con el arrastre glColor3ub(192, 192, 192);
glBegin(GL_POINTS); for(i=xi; i<=xf; i++)
glVertex2i(i,yi), glVertex2i(i,yf);
glVertex2i(xi,i), glVertex2i(xf,i); for(i=xi; i>=xf; i)
glVertex2i(i,yi), glVertex2i(i,yf);
for(i=yi; i>=yf; i)
glVertex2i(xi,i), glVertex2i(xf,i);
glEnd();
//activa el pintado de pixeles glBegin(GL_POINTS);
// pinta posicion del mouse cada 2 segundos con pixeles glColor3ub(228, 0, 0);
for(i=10; i<=10; i++)
glVertex2i(xt+i,yt+i), glVertex2i(xt+i,yti);
// pinta donde hace click en verde glColor3ub(0, 228, 0);
for(i=10; i<=10; i++)
glVertex2i(xi+i,yi), glVertex2i(xi,yi+i);
//termina el pintado de pixeles glEnd();
// pintado instantaneo de la escena glutSwapBuffers();
}
3. Activar el temporizador en GLUT.
Es útil para realizar animaciones o controles interactivos en pasos discretos de tiempo. Para
activar se usa:
glutTimerFunc(33, timer_function, 1);
Y luego se define la función, el siguiente es un ejemplo que imprime la posición del puntero
cada 8 segundos:
void timer_function(int value) {
//mensaje cada 8 segundos
printf("timer func: Posición del puntero %d, %d\n", xt, yt); glutTimerFunc(8000, timer_function, 1);
}