QGLWidget on ubuntu shows nothing - qt

I'm using QGLWidget in a project with Qt5 on ubuntu. The class that extends QGLWidget is very simple, just overiding its two virtual protected functions:
Header:
class MyGLWidget : public QGLWidget {
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
protected:
void initializeGL();
void paintGL();
};
Implementation:
MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent) {
}
void MyGLWidget::initializeGL() {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
}
void MyGLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
}
I created an instance of it and called its show method, expecting a red window to show up, but what I got is:
The window is transparent, it displays whatever underneath it.
What indeed the problem is, and how can I fix it? (I'm using ubuntu 14.04 64bit, the Qt5.3 is installed from qt-project.org directly)

I found the same problem on the same version of Ubuntu and Qt 5.4. I do not know the exact reason but I think it's because the glClear command is not being received or executed by the graphics card unless it is followed by other draw commands. I expanded the paintGL function to include some classic test code like this:
void MyGLWidget::paintGL()
{
glViewport(0, 0, width(), height());
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-20, 20, 20, -20, -1, 1);
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glVertex3f(10, 10, 0);
glVertex3f(-10, 10, 0);
glVertex3f(0, -10, 0);
glEnd();
}
With the additional code to render a red triangle, I found that the clear began to work for me when it had not before.

Related

How to set far clipping plane in QOpenGLWidget?

I am pretty new to Qt so sorry if this is a straight forward question.
I am using Qt 5.5 and trying to visualize a point cloud in QOpenGLWidget.
This is my header:
class PointCloudWindow : public QOpenGLWidget
{
public:
void setDepthMap(DepthMapGrabber* grabber);
protected:
void initializeGL();
void paintGL();
private:
QMatrix4x4 m_projection;
DepthMapGrabber* m_grabber;
};
and here is the corresponding cpp:
void PointCloudWindow::setDepthMap(DepthMapGrabber* grabber) {
m_grabber = grabber;
QTimer* updatePointCloud = new QTimer(this);
connect(updatePointCloud, SIGNAL(timeout()), SLOT(update()));
updatePointCloud->start();
}
void PointCloudWindow::initializeGL() {
glewInit(); // TODO: check for return value if error occured
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void PointCloudWindow::paintGL() {
m_grabber->getNextDepthFrame(); // TODO: check for return value if error occured
m_projection.setToIdentity();
m_projection.perspective(45.0f, width() / (float)height(), 0.01f, 100.0f);
if (m_grabber->getDepthMap()->cloud) {
glBegin(GL_POINTS);
glColor3f(0.8f, 0.8f, 0.8f);
for (UINT i = 0; i < m_grabber->getDepthMap()->size; ++i)
{
glVertex3f(m_grabber->getDepthMap()->cloud[i].X, m_grabber->getDepthMap()->cloud[i].Y, m_grabber->getDepthMap()->cloud[i].Z);
}
glEnd();
}
}
This is how my point cloud looks like after visualization:
My problem is that as you can see (monitor is cut in half for example) if a point has a z value, which is bigger, then 1.0 then it gets clipped of. I tried to set the near and far plane, but no effect. I searched through Google and tried several things, but was unable to figure out how this works in Qt. I manged to visualize this point cloud with OpenGL and GLUT before. Any help or explanation how to do this in Qt would be much appreciated!
m_projection is just a member variable in your class. It's not going to automatically "jump" into the OpenGL context. You've to explicitly load it into OpenGL. Normally you'd load a matrix like that into a uniform for use in a shader. But since you're not using shaders (booo! ;-) ) and use old, ugly and slow immediate mode (don't do that) you'll have to load it into the fixed function projection matrix.
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(m_projection.constData());

Qt just draw the first frame using QGLWidget from QT

I coded a small QT program using QGLWidget. The goal is to display a simple triangle in permanent rotation. The problem is that there is no animation because just the first frame is rendered.
Here's my main C++ source code :
#include "qtapplication.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtApplication w;
w.show();
return a.exec();
}
My qtapplication.h file :
include <QtWidgets/QMainWindow>
#include "ui_qtapplication.h"
#include "HSGLWidget.hpp"
class QtApplication : public QMainWindow
{
Q_OBJECT
public:
QtApplication(QWidget *parent = 0);
~QtApplication();
private:
Ui::QtApplicationClass ui;
HSGLWidget *_glwidget;
};
My qtapplication.cpp file :
#include "qtapplication.h"
QtApplication::QtApplication(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
this->_glwidget = NULL;
if (this->_glwidget == NULL)
this->_glwidget = new HSGLWidget();
this->_glwidget->setVisible(true);
setCentralWidget(this->_glwidget);
}
QtApplication::~QtApplication()
{
}
My HSGLWidjet.h file:
#include <QGLWidget>
class HSGLWidget : public QGLWidget {
Q_OBJECT
public:
explicit HSGLWidget(QWidget *parent = 0);
virtual ~HSGLWidget();
protected:
virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
virtual void keyPressEvent(QKeyEvent *keyEvent);
private:
void _onSetup();
private:
QTimer *_timer;
};
And my HSGLWidjet.cpp file:
#include <iostream>
#include "HSGLWidget.hpp"
float toto_angle = 0.0f;
HSGLWidget::HSGLWidget(QWidget *parent)
: QGLWidget(parent)
{
this->_onSetup();
}
HSGLWidget::~HSGLWidget(void)
{
}
void HSGLWidget::initializeGL()
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.20f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void HSGLWidget::resizeGL(int width, int height)
{
if (height == 0)
height = 1;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void HSGLWidget::paintGL(void)
{
std::cout << "PAINTGL" << std::endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f, 0.0f, -6.0f);
glEnable(GL_MODELVIEW);
glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.0f);
glRotatef(toto_angle, 1.0f, 1.0f, 1.0f);
glScalef(1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLES);
glColor3ub(255, 0, 0);
glVertex3f(0.0f, 0.75f, 0.0f);
glColor3ub(0, 255, 0);
glVertex3f(-0.75f, 0.0f, 0.0f);
glColor3ub(0, 0, 255);
glVertex3f(0.75f, 0.0f, 0.0f);
glEnd();
toto_angle+=1.0f;
glPopMatrix();
}
void HSGLWidget::keyPressEvent(QKeyEvent *keyEvent)
{
}
void HSGLWidget::_onSetup()
{
}
The string 'PAINTGL' is written just for the first frame. Normally, paintGL is called automatically. I'm really lost in front of this situation. Does anyone can help me, please ? Thanks a lot in advance for your help.
There's no problem at all, that's the standard behavior.
You see, paint() and paintGL() are called only when the window needs to be draw. That is: when your application is created, when the window is resized, or moved around. Only then paintGL() is triggered. That's it!
If you want it to be called more than once, you will need to add a timer to execute update(), which is a method that forces the window to be redraw, which in turn triggers paintGL(). Do not call paintGL() directly!
QTimer can help you achieve what you are looking for!

How to look for equivalent functions of OpenGL in QGLWidget?

I'm new to OpenGL and Glut. There is a project implemented by Glut. I googled and found that there is an OpenGL implementation in Qt, called QGLWidget. However, it's hard for me converting the old Glut code to new Qt code since I don't know how to find equivalent function for Glut functions in Qt. Part of the code look like this:
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(gray1->width,gray1->height);
glutInitWindowPosition(100,100);
glutCreateWindow("hello");
init();
glutDisplayFunc(&display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMotionFunc(mouse_move);
glutMainLoop();
The glut* functions above don't exist in Qt's document. So my problem is how can I find equivalent glut functions in functions of QGLWidget?
You need to implement your own class inherited from QGLWidget, for example:
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
};
You also need to override three important functions, initializeGL() where you're preparing your OpenGL. resizeGL() where you update the viewport and projection matrix if your panel is resized, and paintGL() the actual rendering.
The window initialization, of course, is handled by Qt.
For mouse events, there are three functions you can override: mousePressEvent(), mouseMoveEvent(), and mouseReleaseEvent()
void GLWidget::initializeGL()
{
glClearColor(0.5, 0.5, 0.5, 1.0);
}
void GLWidget::resizeGL(int width, int height)
{
glViewport(0, 0, width(), height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width(), 0, height());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
// draw a red triangle
glColor3f(1,0,0);
glBegin(GL_POLYGON);
glVertex2f(10,10);
glVertex2f(10,600);
glVertex2f(300,10);
glEnd();
}
OK. Have you looked at the HelloGL sample?
So there you'll learn how to display a QGLWidget and process mouse input. I think this is what you are looking for.
Since Qt provides SIGNAL and SLOTS input processing is kind of different but also very intuitive. So you have to connect mouse SIGNALS to your SLOTS. Those SLOTS will then process the mouse event.
But look at the sample, it's quite intuitive.

How to use glewInit function from glew.h with QT?

I coded a small QT application (version 5.1.0 (msvc2012_64_opengl), Add-in 1.2.2) in Visual studio 2012. I started with GLU.h include and the program works perfectly. But I want to implement some functions from glew.h. The first thing to do in this case is to call the 'glewInit' method a the top of the 'initializeGL' QT method. But I have the following error :
error lnk2019 unresolved external symbol __glewInit
But I noticed that the code is well exectuted without glewInit but with the #include "glew.h" and not #include "glu.h". So the linkage in the project properties are correct (glu32.lib). So the problem seems to comes from the interaction between QT and my own include of glew.h (I want to say I use glew.h since lots of time without any problem but NOT with QT).
Here's my c++ header file :
#include <gl/glew.h>
#define QT_NO_OPENGL_ES_2
#include <QGLWidget>
//#include <QtOpenGL\qgl.h>
//#include <qtopengl.h>
class HSGLWidget : public QGLWidget {
Q_OBJECT
public:
explicit HSGLWidget(QWidget *parent = 0);
virtual ~HSGLWidget();
protected:
virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
virtual void keyPressEvent(QKeyEvent *keyEvent); /// From QWidget
private:
void _onSetup();
private:
QTimer *_timer;
};
My C++ source file :
#include "HSGLWidget.hpp"
#define QT_NO_OPENGL_ES_2
HSGLWidget::HSGLWidget(QWidget *parent)
: QGLWidget(parent) {
this->_onSetup();
}
HSGLWidget::~HSGLWidget() {
}
void HSGLWidget::initializeGL() {
glewInit();
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.20f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void HSGLWidget::resizeGL(int width, int height) {
if (height == 0)
height = 1;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void HSGLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f, 0.0f, -6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glEnd();
glTranslatef(3.0f, 0.0f, -6.0f);
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3d(1.0f, 1.0f, 0.0f);
glEnd();
}
And my main :
#include <QApplication>
#include "HSGLWidget.hpp"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
HSGLWidget myWin;
myWin.show();
return app.exec();
}
I tried to use #define QT_NO_OPENGL_ES_2 declaration just below my glew.h include definition but it still the same thing. I 'm really lost in front of this situation.
Does anyone can help me?
Linking failure?
Project options-> Linker-> Input
Put there the glew(For example on my project: glew32.lib)
Hope this helped you

Integrating OpenCV with larger programs

Can anyone recommend a how-to guide or provide a brief overview of what's involved with integrating OpenCV with larger GUI-based programs? What are the popular ways to do it?
Particularly, processing video with OpenCV while doing video capture/preview without using HighGUI seems especially arcane. I hope someone can demystify this.
My particular configuration is with either Juce or Qt depending on what can be done. The cross platform thing is not critical -- if there is an awesome way of doing this in Windows, I might be convinced. The availability of community support is important.
I have heard that HighGUI is entirely for testing and unsuitable for real applications. Someone recommended the VideoInput library, but it is experimental.
Key points from answers:
Use Qt (because Qt is great and has a big community).
Open a new thread to run cv::VideoCapture in a loop and emit signal after frame capture. Use Qt's msleep mechanism, not OpenCV. So, we are still using OpenCV highgui for capture.
Convert cv::Mat to QtImage:
QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
qtFrame = qtFrame.rgbSwapped();
Optional: Render with GLWidget. Convert QtImage to GLFormat with Qt built-in method:
m_GLFrame = QGLWidget::convertToGLFormat(frame);
this->updateGL();
Here is how I am doing it with Qt. You are welcome to use whatever may be useful to you :)
/// OpenCV_GLWidget.h
#ifndef OPENCV_GLWIDGET_H_
#define OPENCV_GLWIDGET_H_
#include <qgl.h>
#include <QImage>
class OpenCV_GLWidget: public QGLWidget {
public:
OpenCV_GLWidget(QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0);
virtual ~OpenCV_GLWidget();
void renderImage(const QImage& frame);
protected:
virtual void paintGL();
virtual void resizeGL(int width, int height);
private:
QImage m_GLFrame;
};
#endif /* OPENCV_GLWIDGET_H_ */
/// OpenCV_GLWidget.cpp
#include "OpenCV_GLWidget.h"
OpenCV_GLWidget::OpenCV_GLWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) :
QGLWidget(parent, shareWidget, f)
{
// TODO Auto-generated constructor stub
}
OpenCV_GLWidget::~OpenCV_GLWidget() {
// TODO Auto-generated destructor stub
}
void OpenCV_GLWidget::renderImage(const QImage& frame)
{
m_GLFrame = QGLWidget::convertToGLFormat(frame);
this->updateGL();
}
void OpenCV_GLWidget::resizeGL(int width, int height)
{
// Setup our viewport to be the entire size of the window
glViewport(0, 0, width, height);
// Change to the projection matrix and set orthogonal projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void OpenCV_GLWidget::paintGL() {
glClear (GL_COLOR_BUFFER_BIT);
glClearColor (0.0, 0.0, 0.0, 1.0);
if (!m_GLFrame.isNull()) {
m_GLFrame = m_GLFrame.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_GLFrame.width(), m_GLFrame.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_GLFrame.bits() );
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(0, m_GLFrame.height());
glTexCoord2f(0, 1); glVertex2f(0, 0);
glTexCoord2f(1, 1); glVertex2f(m_GLFrame.width(), 0);
glTexCoord2f(1, 0); glVertex2f(m_GLFrame.width(), m_GLFrame.height());
glEnd();
glDisable(GL_TEXTURE_2D);
glFlush();
}
}
This class handles the rendering of the image onto a promoted QWidget. Next, I created a thread to feed the widget. (I cheated using the Qt signal-slot architecture here because it was easy...may not be the best performer in the book, but it should get you started).
void VideoThread::run()
{
cv::VideoCapture video(0);
while(!m_AbortCapture)
{
cv::Mat cvFrame;
video >> cvFrame;
cv::Mat gray(cvFrame.size(), CV_8UC1);
cv::GaussianBlur(cvFrame, cvFrame, cv::Size(5, 5), 9.0, 3.0, cv::BORDER_REPLICATE);
cv::cvtColor(cvFrame, gray, CV_RGB2GRAY);
m_ThresholdLock.lock();
double localThreshold = m_Threshold;
m_ThresholdLock.unlock();
if(localThreshold > 0.0)
{
qDebug() << "Threshold = " << localThreshold;
cv::threshold(gray, gray, localThreshold, 255.0, cv::THRESH_BINARY);
}
cv::cvtColor(gray, cvFrame, CV_GRAY2BGR);
// convert the Mat to a QImage
QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
qtFrame = qtFrame.rgbSwapped();
// queue the image to the gui
emit sendImage(qtFrame);
msleep(20);
}
}
Took me a bit to figure that out, so hopefully it will help you and others save some time :D
Create an openCV image to hold the image you have captured.
Do processing on it and then copy the data into the image you want to display (eg QImage)
You can optomise things by creating the opencv cv::Mat image to share the memory with the
QImage but since QImage generally uses ARGB and most image processing tasks are better done as greyscale or RGB it's probably better to copy images and convert between them using the opencv cvtColor() function
Then simply include include the opencv headers, and link with the opencv libs - there are guides on the opencv wiki for your particular environment

Resources