El punto que trataremos a continuación tiene que ver con el empleo de la librería gráfica OpenGL dentro del ambiente de ventanas que crea xforms.
La librería xforms permite emplear áreas especiales dentro de las formas o ventanas llamadas 'canvas'. Estas áreas relegan al programador la tarea de manejar la interacción. Existe un tipo de área en particular llamado glcanvas que permite el despliegue de gráficas a partir de la librería OpenGL.
OpenGL es una libería portable que hace uso de los recursos de hardware para crear gráficas de alto rendimiento. Consiste de un conjunto de funciones que permiten desplegar 'primitivas' gráficas, tales como puntos, líneas, poligonos y también permite iluminar y mover una cámara. Se trata, al igual que xforms, de una librería de funciones en lenguaje C.
El problema con el que nos enfrentamos al utilizar estas dos librerías juntas fue en el momento en que quisimos tener varias áreas gráficas dentro de una misma forma. El problema ocurre pues cada área gráfica tiene un 'rendering context' y es necesario activar cada contexto antes de dibujar algo en el. Para mayor información sobre los contextos en openGL, véase "OpenGL graphics with the X window system. Version 1.3 por Paula Womack y John Leech".
La solución fue tener una operación llamada Activa() dentro del área gráfica.
bool C_AreaGrafica::Activa(Display
*dpy,GLXDrawable draw,void *ctx)
{
return glXMakeCurrent(dpy,draw,(GLXContext)
ctx);
}
Del lado de las ventanas que tienen el área gráfica, se tiene que llamar a esta función desde RecibeEvento(), la función que aparte de DespachaCallback() se declara 'static' y que es el callback asignado a los eventos que ocurren en el área gráfica. (Ejemplo tomado de C_VentanaPrincipal)
int C_VentanaPrincipal::RecibeEvento(FL_OBJECT
*ob, Window win,int w,int h, XEvent *xev,void *ud)
{
C_VentanaPrincipal
*ApTemp;
// Apuntador temporal
ApTemp=(C_VentanaPrincipal
*)ob->form->u_vdata; // Rescata
el this
ApTemp->Pantalla.Activa(fl_display,win,ApTemp->forma->canvas->u_vdata);
ApTemp->Pantalla.CambiaTamano(w,h);
// Envia actualizaciones a la pantalla
ApTemp->RefrescaAreaGrafica();
return 0;
}
Es necesario llamar a la operación Activa desde aqui, ya que sólo RecibeEvento() recibe los parámetros necesarios.
Si se tienen múltiples áreas gráficas, se resuelve teniendo dentro de la clase un atributo que indique cual de las tres áreas debe ser activada.
6.4 Desplegando imágenes con OpenGL.
La aplicación que hemos desarrollado consiste principalmente del despliegue de imágenes en areas de dos dimensiones. Aunque la librería OpenGL permite dibujar en 3D, hemos trabajado con formato de enteros (OpenGL permite trabajar múltiples formatos), con la esquina superior izquierda como origen (0,0).
Sin embargo, al querer desplegar imágenes, OpenGL resulto no ser tán rapido como se esperaba. Aunque dispone de funciones que permiten desplegar un arreglo de puntos (en particular glDrawPixels()), estas funciones resultaron ser identicas en velocidad que el despliegue de la imagen 'punto por punto'.
Finalmente fue más útil el despliegue punto a punto pues permitio el uso de funciones de escalado de imágenes.
6.5 Implementación de itoa en una clase de funciones externas.
Al querer mostrar un número en xforms, muchas veces es necesario desplegarlo como cadena. Sin embargo, la función 'itoa()' que cambia un entero a caracteres ASCII, no es una función 'estándar'. Para implementarla se creo una clase 'exclusiva' para ella, se llama C_Externs.
Está declarada como sigue:
#ifndef Externs_C
#define Externs_C
class C_Externs
{
public:
void itoa(int,char
*); // Convierte entero a ascii
};
#endif
Así cuando se necesita llamar a la función, se hace uso de un objeto instanciado a partir de esta clase.
Esta solución es poco elegante, sin embargo, permite respetar el modelo.
6.6 Uso de 'make' para compilar la aplicación.
Para compilar la aplicación hemos hecho uso de la herramienta 'make'. A continuación se muestra el archivo 'makefile' que se empleo para la primera versión.
# Makefile de la aplicacion
de reconstruccion 3D por
# Humberto Cervantes
para el proyecto terminal 1998.
# -------------------------
MACROS ---------------------------
# OBJECTS es una macro
que indica todos los objetos de los cuales depende
# la aplicacion para
compilarse de manera exitosa.
OBJECTS=Main.o Aplicacion.o Manejador.o VentanaPrincipal.o VentanaSelAlgoritmo.o Stack.o DialogoArchivo.o Imagen.o Color.o AreaGrafica.o VentanaConfStack.o VentanaConfStackDisp.o StackConfig.o Externs_C.o Coleccion.o Procesador.o ProcSegUmbral.o VentanaConfSegUmbral.o Histograma.o VentanaReconstruccion.o ProcReconstruccion.o Punto.o ListaLigada.o Volumen.o VentanaAcercaDe.o
# A continuacion aparecen
macros que indican las librerias con las cuales se
# debe ligar la aplicacion
LIBFORMS=-L ../FORMS
-lforms
LIBOGL=-lX11 -lXm -lGL
# INCXFORMS es una macro
que indica que directorios buscar para incluir los
# archivos de cabecera
de xforms.
INCXFORMS=-I ../FORMS
# VENTANAS es una macro
que indica todos los archivos de los cuales depende el
# manejador.
VENTANAS=Ventana.h VentanaPrincipal.h VentanaSelAlgoritmo.h DialogoArchivo.h VentanaConfStack.h VentanaConfSegUmbral.h VentanaReconstruccion.h VentanaAcercaDe.h
#WARNINGS si esta definido como =-w no se mostraran warnings a la hora de compilar...
WARNINGS=-fullwarn -O3
# ------------------------- BUILDS ---------------------------
# __ APLICACION DE MANERA GLOBAL __
Main: ${OBJECTS}
CC -o $@ ${OBJECTS}
${LIBFORMS} ${LIBOGL} -lm
# __ INDEPENDIENTES DE SISTEMA DE VENTANA Y GRAFICOS __
Main.o: Main.cpp Aplicacion.h
CC ${WARNINGS}
-c Main.cpp
Aplicacion.o: Aplicacion.cpp
Aplicacion.h ObjetoInt.h Manejador.o Stack.o Procesador.o ListaLigada.o
CC ${WARNINGS}
-c Aplicacion.cpp
Coleccion.o: Coleccion.cpp
Coleccion.h ObjetoInt.h ObjetoModificable.h AreaGrafica.o
CC ${WARNINGS}
-c Coleccion.cpp
Stack.o: Stack.cpp Stack.h
Coleccion.o Imagen.o StackConfig.o ListaLigada.o
CC ${WARNINGS}
-c Stack.cpp
StackConfig.o: StackConfig.h
StackConfig.cpp
CC ${WARNINGS}
-c StackConfig.cpp
Imagen.o: Imagen.cpp
Imagen.h General.h ListaLigada.o DatoDeColeccion.h
CC ${WARNINGS}
-c Imagen.cpp
Color.o: Color.cpp Color.h
General.h ListaLigada.o
CC ${WARNINGS}
-c Color.cpp
Procesador.o: Procesador.cpp
Procesador.h Proceso.h
CC ${WARNINGS}
-c Procesador.cpp
ProcSegUmbral.o: ProcSegUmbral.cpp
ProcSegUmbral.h Proceso.h
CC ${WARNINGS}
-c ProcSegUmbral.cpp
ProcReconstruccion.o:
ProcReconstruccion.cpp ProcReconstruccion.h Proceso.h Volumen.o
CC ${WARNINGS}
-c ProcReconstruccion.cpp
Histograma.o : Histograma.cpp
Histograma.h Imagen.o
CC ${WARNINGS}
-c Histograma.cpp
Punto.o : Punto.cpp Punto.h
General.h ListaLigada.o DatoDeColeccion.h
CC ${WARNINGS}
-c Punto.cpp
ListaLigada.o : ListaLigada.cpp
ListaLigada.h General.h
CC ${WARNINGS}
-c ListaLigada.cpp
Volumen.o : Volumen.cpp
Volumen.h General.h Punto.o Color.o
CC ${WARNINGS}
-c Volumen.cpp
# __EXTERNOS DE C__
Externs_C.o:Externs_C.h
Externs_C.cpp
CC ${WARNINGS}
-c Externs_C.cpp
# __CONTIENEN COMANDOS DE XFORMS__
Manejador.o: Manejador.cpp
Manejador.h ObjetoInt.h ${VENTANAS}
CC ${INCXFORMS}
${WARNINGS} -c Manejador.cpp
VentanaPrincipal.o: VentanaPrincipal.cpp
VentanaPrincipal.h General.h Ventana.h Aplicacion.o AreaGrafica.o Color.o
CC ${INCXFORMS}
${WARNINGS} -c VentanaPrincipal.cpp
VentanaSelAlgoritmo.o:
VentanaSelAlgoritmo.cpp VentanaSelAlgoritmo.h General.h Ventana.h Aplicacion.o
CC ${INCXFORMS}
${WARNINGS} -c VentanaSelAlgoritmo.cpp
VentanaConfStack.o: VentanaConfStack.cpp
VentanaConfStack.h General.h Ventana.h Stack.h
CC ${INCXFORMS}
${WARNINGS} -c VentanaConfStack.cpp
VentanaConfStackDisp.o:
VentanaConfStackDisp.cpp VentanaConfStackDisp.h General.h Ventana.h Stack.o
StackConfig.o
CC ${INCXFORMS}
${WARNINGS} -c VentanaConfStackDisp.cpp
VentanaConfSegUmbral.o:
VentanaConfSegUmbral.cpp VentanaConfSegUmbral.h General.h Ventana.h Stack.o
StackConfig.o AreaGrafica.o Histograma.o
CC ${INCXFORMS}
${WARNINGS} -c VentanaConfSegUmbral.cpp
DialogoArchivo.o: DialogoArchivo.cpp
DialogoArchivo.h General.h ObjetoInt.h Ventana.h Stack.o
CC ${INCXFORMS}
${WARNINGS} -c DialogoArchivo.cpp
VentanaReconstruccion.o:
VentanaReconstruccion.cpp VentanaReconstruccion.h General.h Ventana.h AreaGrafica.o
Stack.o ProcReconstruccion.o
CC ${INCXFORMS}
${WARNINGS} -c VentanaReconstruccion.cpp
VentanaAcercaDe.o: VentanaAcercaDe.cpp
VentanaAcercaDe.h General.h Stack.h
CC ${INCXFORMS}
${WARNINGS} -c VentanaAcercaDe.cpp
# __CONTIENEN COMANDOS DE OPENGL__
AreaGrafica.o: AreaGrafica.cpp
AreaGrafica.h General.h Color.o Imagen.o
CC ${WARNINGS}
-c AreaGrafica.cpp
# ------------------------------------------------------------
Notese que estan separados los archivos que se pueden compilar independientemente
de las librerias, los que conciernen a xforms y finalmente aquellos que
conciernen a openGL.