PDA

View Full Version : OpenGL with Graphics View?



Dutch112
30th April 2009, 18:46
I am making an application that has a lot of animations going on and would like to make "pure" opengl calls to do this.

Right now I am using the GraphicsView framework and add a bunch of items to the scene. Some items are simple, like buttons. Others are rotating images, for example I have 25 fans rotating on the screen. For this I am using the time line stuff.

I already set the viewport to qglwidget but the hardware I run this on still gets bogged down a bit.

Could I do something like this:



MyQGraphicsItem::paint()
{
quad(x1,y1,...)
glRotatef(...)
}


Or would I have to overpaint in a QGLWidget to do this and not use the graphics view framework?

zaghaghi
30th April 2009, 19:41
you can drive a class from QGLWidget and then use this widget in scene->addWidget


class myQtWidget: public QGLWIdget
{
public:
myQtWidget();
~myQtWidget();
protected:
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
}

Dutch112
4th May 2009, 16:56
When I add my QGLWidget to the scene, nothing draws.

A simple example I'm trying to get working is taking the GLWidget from Qt's HelloGL example then doing the following:



int main(int argc, char **argv)
{
QApplication app(argc, argv);

GLWidget *glWidget = new GLWidget;

QGraphicsScene scene;
scene.addWidget( glWidget );

GraphicsView view;
view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
view.setViewportUpdateMode(QGraphicsView::FullView portUpdate);
view.setScene( &scene );
view.show();

view.resize(1024, 768);

return app.exec();
}


The widget's paintGL() function does get called when I set a breakpoint so it seems like it is trying to draw at least.

Anyone know what I'm missing?

k2
4th May 2009, 17:57
Try subclassing QGraphicsScene and drawing in the overridden QGraphicsScene::drawBackground() function.

See: http://doc.trolltech.com/qq/qq26-openglcanvas.html

wysota
4th May 2009, 21:03
Or would I have to overpaint in a QGLWidget to do this and not use the graphics view framework?

You can make the QGLWidget a viewport of the graphicsview and then use pure GL calls inside the items' paint() routines to do the painting, that's not a problem. You can even mix GL and QPainter based items if you want. Either way be sure to draw in the right coordinates (remember about the bounding rect and transformations applied to items).

Dutch112
4th May 2009, 21:26
You can make the QGLWidget a viewport of the graphicsview and then use pure GL calls inside the items' paint() routines to do the painting, that's not a problem. You can even mix GL and QPainter based items if you want. Either way be sure to draw in the right coordinates (remember about the bounding rect and transformations applied to items).

Is this preferable to creating a subclass of QGLWidget and trying to add that widget to the scene?

Dutch112
4th May 2009, 21:30
Try subclassing QGraphicsScene and drawing in the overridden QGraphicsScene::drawBackground() function.

See: http://doc.trolltech.com/qq/qq26-openglcanvas.html

I tried adding the glWidget to a control and to the scene itself. I also call update() on the widget inside of the scene's drawBackground. Still no luck.

Tried


QWidget *controls = createDialog(tr("Controls"));
glWidget = new GLWidget;
controls->layout()->addWidget(glWidget);
addWidget(controls);


Tried


glWidget = new GLWidget;
addWidget(glWidget);


Tried


void OpenGLScene::drawBackground()
{
glWidget->updateGL();
....
}

wysota
4th May 2009, 22:12
Is this preferable to creating a subclass of QGLWidget and trying to add that widget to the scene?

From what I know this will currently not work.

k2
5th May 2009, 18:54
I tried adding the glWidget to a control and to the scene itself. I also call update() on the widget inside of the scene's drawBackground. Still no luck.

Tried


void OpenGLScene::drawBackground()
{
glWidget->updateGL();
....
}


You no longer use OpenGL commands in the glWidget's paintGL() function (in fact you don't need to subclass QGLWidget at all - one just needs to be set as the GraphicsView's viewport), you do them in drawBackground(). Also, you don't call updateGL(), just call update() inside of OpenGLScene::drawBackground() which will queue another call to drawBackground() (in the example link, they use a QTimer and singleShot to limit the number of update() calls and thus the framerate).

Add widgets using the OpenGLScene::addWidget() function.

See the link I provided, it shows how to mix an OpenGL scene with embedded Qt widgets using the GraphicsView framework.

olidem
18th May 2009, 12:10
Hi!

I followed the discussion and I am very interested in being able to use OpenGL commands inside the paint() code of the items in my scene. Actually, I have started implementing this, with great success.

Here's a schematic overview of how I've done:


//...
QGraphicsScene scene;
QGraphicsView view(&scene);
//the following line adds the opengl support
view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers | QGL::Rgba)));

//here's my item class
class GLGraphicsItem : public QGraphicsItem
{
//...
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
if (painter->paintEngine()->type() != QPaintEngine::OpenGL)
qWarning("OpenGLScene: drawBackground needs a "
"QGLWidget to be set as viewport on the "
"graphics view");
else{
//opengl commands here
}
}
//...
}//end-class

The ablove code works nicely and does what it shoud - if I just display the view.

Now I tried to use the view function


QGraphicsView::render ( QPainter * painter, const QRectF & target = QRectF(), const QRect & source = QRect(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio )

which will output the warning message, i.e. this rendering is performed *without* opengl support.

I do not need the fastest hardware acceleration for this offscreen rendering at this point, just the opengl commends are very important for me.

wysota
18th May 2009, 20:15
Where do you render to using the above call?

olidem
18th May 2009, 20:28
You mean the call to QGraphicsView::render() ?
Well, I want to copy the contents of my scene, or to be more precise: I want to render my scene as it is shown by the view into an image . Eg. a qImage, or a Printjob could be such a target.

What I found out meanwhile is QGLWidget::grabFramebuffer(), which partly does the job.
The big disadvantage of this funtion is that it just gives you exactly the resolution of the QGLWidget as it is shown.

wysota
18th May 2009, 20:54
Render to a QGLFrameBuffer object and then use QGLFrameBuffer::toImage() to convert the result to an image.

ricardo
19th May 2009, 00:42
From what I know this will currently not work.

I'm doing to create my game level editor and everything works fine.


@Dutch112. How are you going to control your animation time? are you going to use QTimer or just a common loop game?

olidem
19th May 2009, 08:48
Well, that's not so easy.
First, AFAIK not every system supports these framebuffers. Pls correct me if I'm wrong.

Secondly, I would have to initialize (initializeGL, resizeGL and paintGL) this new OpenGL object. As I am doing it up to now, all these initialisations are already done for me by the Qt subsystem.
This means that I would have to ready out the projection and modelview matices everytime and keep a copy of them locally up to date.

wysota
19th May 2009, 09:21
It's either this or grabbing the widget or forgetting about GL... You can't use GL calls on a non-gl context and if you want a canvas that is different than the widget you have to set it up separately.