Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QGraphicsScene is missing a particular item update

I've got an application where you can watch replays for a given 2D game :

Basically, a vehicle is moving on a map. The view is centered on vehicle so the map is scrolling as replay is playing, something Micro Machines-like (it's just to give an idea, the actual game is not Micro Machines).


(source: randomracket.com)

In my scene, the map is static while the vehicle is moving around. The view is scrolling for each frame of the replay, so that vehicle is centered. For performance reason, the map is tiled in several QGraphicsPixmapItems.

Viewport update mode is set to QGraphicsView::BoundingRectViewportUpdate. Items index method is set to QGraphicsScene::NoIndex.

In most cases, all is working fine. But when the map is larger than usual, the vehicle is not updated. The view is scrolling and tiles are well updated; but not the vehicle, unless I trigger a full viewport update by zooming in/out (so I know the item is well positioned).

The vehicle's boundingRect is set once for ever, and is valid (see below, given in logical coordinates). I do not paint outside item's bounding rect.

some example of debug output (only third configuration does not work) :

ok :
vehicle->boundingRect() : QRectF(-1.9391,-1.9391 3.8782x3.8782)
scene->sceneRect() : QRectF(-117.543,-38.3826 138.834x40.3217)
SCENE_CACHING : 85 tiles

ok :
vehicle->boundingRect() : QRectF(-2.88489,-2.88489 5.76979x5.76979)
scene->sceneRect() : QRectF(-68.8843,-18.2202 187.989x119.277)
SCENE_CACHING : 308 tiles

nok : vehicle won't update
vehicle->boundingRect() : QRectF(-3.45546,-3.45546 6.91092x6.91092)
scene->sceneRect() : QRectF(-64.2988,-107.802 188.927x187.445)
SCENE_CACHING : 506 tiles

I tried to debug an update pass, and the paint event indeed excludes the region where vehicle is...

Anyone know why an update could miss a particular item ?

Edit :

Qt : 4.8.1, and i've seen the problem with previous versions as well

OS : Windows XP SP3, did not test on other OS yet

I did not succeed in reproducing the problem with a minimal example. The minimal example just work like it is expected to do. In real life, here is what is done :

  1. The map is read from a file. It's composed of up to hundreds of polygons delimiting ground/sky (each one of which is graphically made of polygons, edges and vertices layers), thousands of pictures and textures which are then clipped to ground or sky, and some other items.

  2. I compute all the clippings, and then render the scene in a QImage. The image is tiled in several QGraphicsPixmapItems added to the scene, while the former items are removed from scene and deleted (btw the bug also occured when I didn't remove&delete former items).

  3. The replay is launched

I think Qt Graphics internals are messed up, but I can't figure out how to clean/reset it.

Here is an example of graphics (to illustrate what I mean by ground/sky). The map can be quite huge.


(source: kopasite.net)

like image 831
azf Avatar asked Oct 07 '22 13:10

azf


1 Answers

Picking up my comment from above as an answer:

You need to use QGraphicsScene::invalidate(...) to invalidate the parts of the scene that should be redrawn.

like image 78
Johannes S. Avatar answered Oct 12 '22 10:10

Johannes S.