Usando OpenGL con QT Creator

images

ADVERTENCIA: Para entender este artículo, es necesario tener conocimientos previos de C, C++, QT, QT Creator, OpenGL, Gráficos 3D, Programación orientada a objetos, Alta costura, cocina francesa, Física Cuántica, … y si sabe todo eso, tal vez ya no tenga que leer esto.

CONTENIDO

Bien es sabido que QT viene con las pilas puestas para OpenGL, de modo que no será muy difícil (siempre considerando nuestra escala personal de «difícil») usar la librería OpenGL, dentro de nuestros programas en QT.

Para empezar diré que voy a usar QT Creator 3.4.2 sobre QT 5.5.0, con el compilador de Visual C++, sobre Windows, y como último detalle, «insignificante», debo decir que no soy un experto en QT, de modo que no me responzabilizo por daños materiales o sicológicos, y como siempre las correcciones son bienvenidas.

Para empezar, vamos desde el principio, de seguro que hay formas retocidas de usar OpenGL en QT (para ver las formas retorcidas de usar OpenGL en QT pulsé aquí, si el enlace no está activo es que aún no encuentro estas formas retorcidas), pero aquí voy a seguir el método «estándar», por así decirlo, que es el que he visto que se usa más.

Este método consiste en usar la clase QGLWidget (o su hermano casi olvidado QOpenGLWidget), que viene ya preparada para manejar la salida gráfica de OpenGL, y es de bastante ayuda porque uno de los principales problemas de la librería gráfica OpenGL, es que no tiene un lienzo donde graficar, y QGLWidget le da precisamente eso. Además es bueno recordar que QGLWidget es como la clase QWidget (si es que eso ayuda en algo) solo que viene preparada para dibujar usando OpenGL, aunque puede usar también QPainter, si se lo pedimos amablemente.

El uso de QGLWidget  es sencillo, basta derivar una clase para usarla como pantalla de dibujo OpenGL y luego implementar los métodos necesarios. ¿Cómo se hace esto?, pues vamos a seguir la siguiente receta, como ejercicio:

Crear Proyecto

Crear un proyecto nuevo de tipo «Qt Widget Application». No olvidar que estamos usando QT Creator (me reservo mi opinión sobre esta IDE).

NuevoProyecto

El nombre que vamos a elegir para el proyecto es «MiOpenGL». Dejar todos los demás valores por defecto.

Agregando las Malvadas Referencias

¿Quién dijo que QT, te facilita la vida? No señores, hay nuchas cosas que debemos hacer a mano.

Agregar las referencia a «opengl» y a la librería «opengl32.lib», en el archivo de proyecto MiOpenGL.pro, en los puntos indicados:

ReferencQT

Si olvidamos estas referencias, obtendremos los diabólicos y nada descriptivos errores «LNK-0666 – Error en alguna referencia de la que no tengo ni idea, así que estas muerto###»

Y lo más molesto, es obligatorio, repito OBLIGATORIO, hacer un «QMake», después de modificar el archivo MiOpenGL.pro.

Para ver si todo va bien hasta aquí, es recomendable ejecutar el programa para ver si hay errores.

Crear una clase de QGLWidget

En el menú contextual del proyecto, seleccionar «>Add New…>C++>C++ Class», para agregar una nueva clase, a la que llamaremos «GLWidget»:

nuevaclase

Las demás opciones, dejarlas por defecto. El contenido de la clase debe quedar así:

———————————————– glwidget.h —————————————————–

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QGLWidget>

class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent = 0);

signals:

public slots:
};

#endif // GLWIDGET_H

———————————————– glwidget.cpp —————————————————–

#include «glwidget.h»

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{

}

————————————————————————————————————————

Este contenido no se genera directamente desde el QT Creator, así que hay que corregirlo a mano. La idea es heredar de QGLWidget, en lugar de QWidget.

Dándole forma a QGLWidget

Una vez que tenemos la clase, es necesario implementar los métodos virtuales  (si no tiene idea de lo que esto significa, debe saber que hay mucha información en la Web) de QGLWidget, en la declaración:

protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();

Y en la implementación haremos la más sencilla de las implementaciones:

void GLWidget::initializeGL()
{
glClearColor(0, 0, 1, 1);   //define color azul como color de fondo
}

void GLWidget::resizeGL(int w, int h)
{
}

void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
}

Estos 3 métodos son los mínimos que se necesitan implementar de QGLWidget, en nuestra clase, para poder mostrar gráficos usando OpenGL.

Los nombres son descriptivos así que no merecen más explicación. Solo nos bastará con saber que el método initializeGL(), se llamará solo una vez al iniciar nuestro programa, mientras que el método paintGL(), es llamado repetidamente cada vez que se solicita dibujar la imagen. En nuestro ejemplo, lo único que se hace en paintGL() es limpiar el fondo usando el color definido con glClearColor(), que en nuestro caso es azul, ya que los parámetros son de tipo RGB, con el último parámetro representando a la opacidad.

En resumen lo que hemos hecho hasta aquí es crear una clase derivada de QGLWidget, y la hemos personalizado para que dibuje lo que querramos, pero eso es todo. Aún no se dibuja nada, porque nuestra clase es una estructura sin parte visual, una maniquí sin cara.

Dadme un Widget y dibujaré en 3D

Ahora que ya hemos implementado una clase elemental a partir de QGLWidget, necesitamos darle una pantalla, para que se pueda ver.

Esto lo obtendremos, usando un control (un Widget) en donde se pueda dibujar. Miren como son las casualidades, precisamente existe uno en QT Creator, que se adapta bien. Se llama «Widget».

Lo que tenemos que hacer, es arrastrar un control «Widget» a nuestro formulario y dimensionarlo, como nos sea más conveniente:

WidgetEnQT

Ahora ya tenemos un control que puede mostrar nuestros gráficos en pantalla, pero es un simple Widget, y no tiene nada que ver con nuestra clase GLWidget. Lo que se debe hacer es lo que se llama «promover», nuestro Widget para que herede las funcionalidades de nuestra clase GLWidget, en lugar de mantener las funcionalidades de un simple Widget.

Para ello, lo que debemos hacer, es seleccionar nuestro control o Widget en el formulario y seleccionar la opción «Promote to …»:

PromoteToQT

En este formulario, debemos escribir el nombre de nuestra clase GLWidget, luego pulsar el botón «Add», marcar el elemento de la lista superior y finalmente pulsar el botón «Promote»:

PromoteToQT2

Luego de realizar esta «promoción», ya nuestro Widget evoluciona para ser ahora un GLWidget y seguir nuestras órdenes.

Se puede obsrevar que ahora nuestro control Widget aparece como un objeto GLWidget en el panel de objetos.

Para verificar que no hemos metido la pata, podemos ejecutar nuestro programa, y debemos obsrevar un formulario con un cuadro azul en el centro:

glqt1

Ahora sí, dibujemos

Valgan verdades, hasta ahora no hemos dibujado nada, solo hemos limpiado el lienzo. Eso está muy bien, y demuestra que vamos por buen camino, ahora podemos demostrar nuestras dotes de dibujante, agregando instrucciones OpenGL adicionales.

El lugar para hacer eso es, como ya adivinó, en el método paintGL()  de nuestra clase GLWidget. No voy a explicar aquí las funciones de dibujo de OpenGL, solo usaré las que se necesitan para dibujar un triángulo simple:

void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.6 ,0.3, 0);
glVertex3f(-0.9, -0.3, 0);
glVertex3f(-0.3 , -0.3, 0);
glEnd();
}

Con estas instrucciones, y un poco de geometría, estamos diciendo que queremos dibujar un triángulo de color rojo en la pantalla. Ahora, si hemos hecho las cosas bien, debemos poder obtener el siguiente resultado:

traingOpenGL

Puede que sea necesario ajustar el tamaño de la ventana, o las coordenadas para lograr esta obra maestra.

Bueno, eso es todo. Este artículo es solo el comienzo para empezar a trabajar con OpenGL y QT. A partir de aquí se puede complicar más el programa para obtener mejores resultados, pero no hay que olvidar que todo buen programa requiere un buen diseño, después de todo, hasta las pirámides de Egipto se diseñaron (no se empezó poniendo piedra por piedra), y eso fue hace varios miles de años.

 


2 comentarios

  1. Muy amable, gracias por compartir la presente entrada; por mi parte ando buscando la manera de presentar gráficos a través de un programa que estoy construyendo en QT para mi tesis, a la vez esta debe presentar información que se lea de una base de datos, bueno hay más, me gustaría poder estar en contacto contigo, un saludo.

Dejar una contestacion

Tu dirección de correo electrónico no será publicada.


*