«

»

Nov 04

How I fell for QGLViewer for my Qt/OpenGL projects [w/ code]

While looking for a very simple way to start up an OpenGL visualizer for quick 3D hacks, I discovered an excellent library called libQGLViewer, and I want to quickly show how easy it is to setup a 3D environment with it. This library provides an easy to access and feature-rich QtWidget you can embed in your UIs or use stand-alone (this may sound like a marketing thing, but they are not paying me anything :)

This is based on the library's own examples at: http://www.libqglviewer.com/examples/index.html, and some of the examples that come with the library source itself.

Let's see how it's done

Let's start a dialog

So libQGLViewer is simply an OpenGL context within a Qt application. What makes it cool is that you can put it inside a complex UI you build with QtDesigner and interact with it.
So let's setup an empty dialog in designer, drag in an empty QtWidget, and set up a vertical layout for the dialog (to put stuff under the widget later):

Now we need to promote the widget so we can make it use QGLViewer:

This is the .ui xml code:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>430</width>
    <height>336</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout_2">
   <item>
    <widget class="MyQGLViewer" name="widget" native="true"/>
   </item>
   <item>
    <layout class="QFormLayout" name="formLayout"/>
   </item>
  </layout>
 </widget>
 <customwidgets>
  <customwidget>
   <class>SkeletonViewer</class>
   <extends>QWidget</extends>
   <header>../MyGLViewer.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

Note I'm referencing an .h file that's in the parent directory, this is because later the compiled .ui will be in the build/ subdirectory.

Next we write down an empty shell for the widget, inheriting from QGLViewer:

#include <QGLViewer/qglviewer.h>

class MyGLViewer : public QGLViewer
{
	Q_OBJECT
	
public:
	MyGLViewer(QWidget *parent = 0);
	
	protected :
	virtual void draw();
	virtual void init();
	virtual QString helpString() const;
		
	public slots:
		
signals:
	
};

And some empty implementation...

#include "MyGLViewer.h"

void MyGLViewer::draw()
{	
        //some 3D
	glColor4f(1.0, 0.5, 0.5, 1.0);
	glutSolidTeapot(0.5);
	glTranslated(1.0, 0, 0);
	glColor4f(0.5, 1.0, 0.5, 1.0);
	glutSolidSphere(0.33, 20, 20);
	glTranslated(-2.0, -0.5, 0);
	glColor4f(0.5, 0.5, 1.0, 1.0);
	glRotated(-90, 1, 0, 0);
	glutSolidCone(0.5, 1.0, 20, 20);

	glColor4f(1.0, 0.0, 0.0, 1.0);
	drawText(20, 20, QString("here will be 3D!"), QFont("Helvetica [Cronyx]", 20));
}

void MyGLViewer::init()
{
	// Restore previous viewer state.
	restoreStateFromFile();	

	setAxisIsDrawn(true);
	
	// Opens help window
	help();
}

QString MyGLViewer::helpString() const
{
	QString text("<h2>My QGLViewer</h2>");
//.... more text?
	return text;
}

// Constructor must call the base class constructor.
MyGLViewer::MyGLViewer(QWidget *parent) : QGLViewer(parent)
{
	restoreStateFromFile();
	help();
}

See make? CMake!

I'm a die hard CMake fan, so I am using it for building up Qt projects as well, instead of Qmake which basically does the same.
So here's a simple CMakeLists.txt to set up our QGLViewer project: (stripped down from http://qt-project.org/quarterly/view/using_cmake_to_build_qt_projects, it's too complicated tl;dr)

cmake_minimum_required (VERSION 2.6) 
project (MyQGLViewer) 

find_package(OpenGL REQUIRED)
find_package(Qt4 REQUIRED QtGui QtOpenGL QtXml)

# Show a little love for OSX..
IF(APPLE)
   INCLUDE_DIRECTORIES ( /System/Library/Frameworks )
   FIND_LIBRARY(COCOA_LIBRARY Cocoa)
   FIND_LIBRARY(GLUT_LIBRARY GLUT )
   FIND_LIBRARY(OpenGL_LIBRARY OpenGL )
   MARK_AS_ADVANCED (COCOA_LIBRARY
                     GLUT_LIBRARY
                     OpenGL_LIBRARY)
   SET(OpenGL_LIBS ${COCOA_LIBRARY} ${GLUT_LIBRARY} ${OpenGL_LIBRARY})
ENDIF (APPLE)


file(GLOB MY_SOURCES	
	*.cpp *.c)
file(GLOB MY_HEADERS	
	*.h)
file(GLOB MY_UIS	
	*.ui)

######## Qt stuff ########
ADD_DEFINITIONS(${QT_DEFINITIONS})
include_directories(${QT_INCLUDES})
include(${QT_USE_FILE}) 

QT4_WRAP_UI( MY_UI_HDRS ${MY_UIS} )
QT4_WRAP_CPP( MY_MOC_SRCS ${MY_HEADERS} )

INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ) #qt wrapping creates some sources
#########################

add_executable(MyQGLViewer ${MY_SOURCES} ${MY_HEADERS} ${MY_UI_HDRS} ${MY_MOC_SRCS})


target_link_libraries(MyQGLViewer
	${OpenGL_LIBS} 
	${QT_LIBRARIES} 
	QGLViewer
	)

Like this CMake also creates build steps for compiling .ui files into .h and .cxx files, which are then added to the build. The things is that you must run the build twice for the ui compilation and then the cpp compilation.

Done!

So that's a simple quick recipe for using OpenGL in Qt environment using libQGLViewer, which is awesome.

I'm not gonna put the code in the repo this time, just cuz' it's all here in the post...

Enjoy,
Roy.

Share
  • alberto

    hi! what about drawing a cv::Mat into opengl? there are some method (dlDrawPixels, texture to a plan, and even others) have you tired some?

  • http://www.morethantechnical.com Roy

    @alberto
    Please see http://web.media.mit.edu/~roys/src/OGL_OCV_common.zip
    There's code there to draw OpenCV Mats to an OpenGL context.