PDA

View Full Version : QGraphicsView and fast moving objects



deMarco
14th January 2009, 06:46
Hi,
I've been making a pong clone using a QGraphicsView, but i seem to have an issue with moving objects rapidly within the view e.g. the ball, which i have updating around 40Hz.

1/ it's blurry.. I expect abit of blur because of the movement, but it seems as if the ball is being painted in it's new position, before the old position has been repainted, ie for an instant it's in two places at once. It makes it kinda difficult to focus (literally) on the ball, though some of this may be subjective.

2/ there's tearing/artifacting. not all the time, but if you watch the ball for 10s or so you'll see it.

I've tried playing around with different caching modes, on both the ball graphicsItem and the graphicsScene itself, but with little success. I've also tried disabling the viewport updates and managing the updating myself, but the same problems occur.

I've included a sandbox example of a ball bouncing around so you can check it out (only compiles for windows, sorry), i must be doing something obvious wrong, as i know GV can handle thousands of items, surely it can handle one fast ball?!

deMarco
15th January 2009, 23:06
hi guys, any suggestions I can try here?

jpn
16th January 2009, 16:57
Perhaps turning of scene's item index method helps a bit?

seneca
16th January 2009, 23:24
Did you experiment with OpenGL to make use of the graphics card processor?

From QGraphicsView:


By default, QGraphicsView provides a regular QWidget for the viewport widget. You can access this widget by calling viewport(), or you can replace it by calling setViewport(). To render using OpenGL, simply call setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport widget.

Bjoern
26th February 2009, 11:07
first of all: when using Qt, please prefer using its methods above using platform dependent stuff.


#include <QtGui/QApplication>
#include <QDebug>
#include "balltest.h"
#include <QTime>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Balltest w;
w.setGeometry( 200, 200, 1024, 768 );
w.show();
QTime prevTime = QTime::currentTime();
while( w.IsRunning() )
{
if( (prevTime.msecsTo(QTime::currentTime())) >= 0.025 )
{
w.Update();
prevTime = QTime::currentTime();
}
a.processEvents();
}
return 0;
}

works on any platform (even though I'd recommend to use a QTimer firing regularly !)

Looked on your code and tried on X11, the "problem" is simply due to the fact that the screen updates are based upon rectangular areas which are repainted one after each other, so depending on the platform / gfx card / driver / processor you'll get more or less tear and flicker.
With OpenGL you'll at least circumvent this partially, because GL renders into an offscreen buffer which is switched after all paint operations are done.
You will still have tearing, which occurs due to the fact that you're changing the screen contents just while it's being displayed, but you can get rid of this when waiting for VBlank (can be adjusted in most graphic card drivers).