1

currently i am trying to laod *.obj-files into my programm. My code is based on this example:

Accelerate your widgets with OpenGL(changed link)

The only differeence in my code, is that i have a glwidget-class, in which all the drawing is defined. In the class OpenGLScene only my Gui is defined. In the function drawBackground(QPainter *painter, const QRectF &) i call the function paintGL.

void OpenGLScene::drawBackground(QPainter *painter, const QRectF &)
{
    if (painter->paintEngine()->type() != QPaintEngine::OpenGL
    && painter->paintEngine()->type() != QPaintEngine::OpenGL2)
{
    qWarning("OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
    return;
}

painter->beginNativePainting();

glClearColor(m_backgroundColor.redF(), m_backgroundColor.greenF(), m_backgroundColor.blueF(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if (m_model) {

    m_model->paintGL();
}

painter->endNativePainting();

}

Simple drawing and stuff works fine. I only get problems until i try to load *.obj-Files. I have tried several things, which didnt work. Now I ended up with the solution to define all the functions from the model-class(which you can find in the example) in my glWidget-Class and then calling the render-function in paintGL. Afterwards calling the paintGL in OpenGLScene.

Here you can see my header-files: OpenGLScene.h and GLWidget.h:

class GLWidget : public QGLWidget
{
Q_OBJECT
public:
float           m_distance;
GLWidget(const QString &filePath);
GLWidget(QWidget *parent = 0);
~GLWidget();
QSize           minimumSizeHint() const;
QSize           sizeHint() const;
void            initializeGL();
void            paintGL();
void            resizeGL(int width, int height);
void render() const;
QString fileName() const { return m_fileName; }
int faces() const { return m_pointIndices.size() / 3; }
int edges() const { return m_edgeIndices.size() / 2; }
int points() const { return m_points.size(); }
QString m_fileName;
QVector<Point3d> m_points;
QVector<Point3d> m_normals;
QVector<int> m_edgeIndices;
QVector<int> m_pointIndices;
};


#ifndef QT_NO_CONCURRENT
#include <QFutureWatcher>
#endif

class GLWidget;

class OpenGLScene : public QGraphicsScene
{
Q_OBJECT

public:
OpenGLScene();
void drawBackground(QPainter *painter, const QRectF &rect);
QDialog *createDialog(const QString &windowTitle) const;

void setModel(GLWidget *model);

//Model       *m_model;
GLWidget    *m_model;
QColor      m_backgroundColor;
float       m_distance;
QLabel      *m_labels[4];
QWidget     *m_modelButton;
#ifndef QT_NO_CONCURRENT
QFutureWatcher<GLWidget *> m_modelLoader;
#endif
public slots:
void loadModel();
void loadModel(const QString &filePath);
void modelLoaded();
};

Unfortunately this idea isnt working, because i get this error:

"It is not safe to use pixmaps outside the GUI thread"

But I really dont understand whats that supposed to mean.

buddy
  • 821
  • 2
  • 12
  • 30
  • Hm…Maybe I should specify it more. My first question would be why it is a problem to define the modelfunctions in glwidget? GLWidget’s content is the same as the model-class content plus some extras. Therefore I dont understand the error: “It is not safe to use pixmaps outside the GUI thread” Because in the OpenGLScene-Class I have nothing changed except the datatype-names. I’ve replaced Model-datatype to GLWidget-datatype. Maybe someone would be able to help me? Or is it so obvious that it is to easy to answer. If so I would be happy if you could share your ideas with me. – buddy Jan 21 '12 at 00:12
  • For all of you who have maybe tried the code from the upper link. I am sorry but this is an old version which is not working. Here is the [new one](http://qt.gitorious.org/qt-labs/modelviewer) Sorry – buddy Jan 21 '12 at 23:16

1 Answers1

1

If you've moved all the Model stuff into GLWidget then I assume you are now creating your GLWidget instance in ::loadModel? If so then be aware that this is being created in a new thread. It looks like it doesn't automatically get moved into the main (GUI) thread when the loading thread finishes. What actually happens to the QObject is an open question.

If you want to disable threading completely in order to simplify things then remove the lines

#ifndef QT_NO_CONCURRENT
#include <QFutureWatcher>
#endif

and

#ifndef QT_NO_CONCURRENT
QFutureWatcher<Model *> m_modelLoader;
#endif

in openglscene.h. In the OpenGLScene constructor body remove the lines

#ifndef QT_NO_CONCURRENT
    connect(&m_modelLoader, SIGNAL(finished()), this, SLOT(modelLoaded()));
#endif

In OpenGLScene::loadModel(const QString &filePath) change

#ifndef QT_NO_CONCURRENT
    m_modelLoader.setFuture(QtConcurrent::run(::loadModel, filePath));
#else
    setModel(::loadModel(filePath));
    modelLoaded();
#endif

to just

    setModel(::loadModel(filePath));
    modelLoaded();

Finally remove

#ifndef QT_NO_CONCURRENT
    setModel(m_modelLoader.result());
#endif

from OpenGLScene::modelLoaded().

Community
  • 1
  • 1
Troubadour
  • 13,334
  • 2
  • 38
  • 57
  • Well, as I understand it, it is not possible to load obj-files as I tried to do. I have tried to push my object into the main-thread but it isnt working. I am a complete newbie to threading. I have researched a little bit on this matter, but I cant get a grip on this. The whole concept of threading seems to be a BIG thing. Might there be another way to load obj.-files? Maybe without threading. From your answer I get the feeling that there might be a possibility. Could you be more specific? Thank you. – buddy Jan 22 '12 at 15:46
  • @buddy: You can certainly remove the threading easily enough as there are two code paths wherever the threading is used. Which one is compiled in is dependent on the QT_NO_CONCURRENT preprocessor macro. Either ensure that this macro is defined at the top of the relevant source files or just comment out the threading code (which is in the `ifndef QT_NO_CONCURRENT` bits). Try this and see if it works. If you want to get it working with threading let me know and I can see what I can do. – Troubadour Jan 22 '12 at 16:07
  • Actually Qt seem to have another problem.I have removed the threading from the unchanged sourcecode.(Where i still have the model class).This is working fine. As soon as I add to the Model class `: public QGLWidget` I get the error: It is not safe to use pixmaps outside the GUI thread. So it seems to be rather the inheritance in general than the threading. And the inheritance I need in GLWidget Do you know why that might be? – buddy Jan 22 '12 at 16:55
  • @buddy: I've updated my answer to outline everything you need to do to ensure you are not threading. Check that you have made all of these changes. – Troubadour Jan 22 '12 at 22:12
  • Sorry for my late response. I had to work the last days. Thank you for your help, it works now. I am not getting why threads should be used, if it is working fine this way. But maybe someday I will start to learn the whole thread-thing. Maybe then it will make sense. Thanks again – buddy Jan 29 '12 at 11:41
  • @buddy: The reason for using threading in this case is to allow the model loading to happen in the background i.e. without freezing the GUI. – Troubadour Jan 29 '12 at 18:34