Seite 1 von 1

Zeichnen beschleunigen, aber wie?

Verfasst: 31. März 2008 17:08
von slash-ex
mir ist irgendwie aufgefallen, das die zeichengeschwindigkeit irgendwie langsam wird, vorallem wenn man den ausschnitt vergrößert. das merkt man daran, dass zum beispiel beim verschieben. die modelle der maus etwas hinterherhinken.
deshlab wollte ich mal fragen wie man generell etwas optimieren kann.

ich dachte evtl dran, nicht bei mouse-events sondern über nen timer zu malen, aber bin nicht sicher ob das was bringen würde.
dann dachte ich dran dinge, die eigentlich nur einmal bei bestimmten events gezeichnet werden müssten und nicht bei einem mausmove zu puffern. aber da weis ich nicht wie das geht und ob überhaupt. kandidaten für sowas wären zum bsp.

Code: Alles auswählen

	drawRangeCircles(*painter, px_painter, pen);
die wird zum bsp über nen tastendruck aufgerufen und kann beim release der maus wieder ausgeblendet werden.

könnte mir da jemand ein paar tips geben, solche recht einfachen sachen sollten doch schneller gehen....

Code: Alles auswählen

void BFItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
	Q_UNUSED(widget);

	// Painter mit Zoll-Koordinatensystem
	painter->setRenderHint(QPainter::Antialiasing);
	painter->setRenderHint(QPainter::SmoothPixmapTransform);
	//! Painter automatisch so skalieren, dass man mit den "Zoll"werten malt.
	painter->scale(*pixels_per_inch, *pixels_per_inch);
	// Painter mit standard Pixel-Koordinatensystem
	QPainter px_painter; 
// 	px_painter->setRenderHint(QPainter::Antialiasing);
// 	px_painter->setRenderHint(QPainter::SmoothPixmapTransform);	

	QPen pen;

	selected = dModel->selected();
	moving = dModel->moving();
	turning = dModel->turning();
	std::cout<<turning<<std::endl;

	/*!
		Modelle zeichnen
	*/
	drawRangeCircles(*painter, px_painter, pen);
	/*!
		Eiheiten zeichnen
	*/
	drawModel(*painter, pen, dModel->position() );
	/*!
		Modelle selektieren
	*/
	drawSelCircles(*painter, px_painter, pen);
	/*!
		Reichweite anzeigen
		!es muss darauf geachtet werden, dass nur selektierte markiert werden (in der board wirds �berpr.)
	*/
	drawRangeCircles(*painter, px_painter, pen);
	/*!
		Modelle drehen
		!es muss darauf geachtet werden, dass nur selektierte markiert werden (in der board wirds �berpr.)
	*/
	drawAngelGrid(*painter, px_painter);
}

Verfasst: 31. März 2008 17:43
von slash-ex
ich glaube fast, das ein timer wirklich das beste wäre, damit könnte ich rechenzeit verteilen. und evtl könnte ich sogar threaden.
aber vorher würde ich echt gerne wissen ob es möglichkeiten gibt irgendwie, bestimmte sachen zu puffern, wie das beim background möglich ist. dieser wird auch nur einmal gezeichnet.

nun wäre das wohl auch ein möglichkeit das prob zu lösen, indem ich ein bild erstelle und das als background nehme. aber leider würde das den code ziemlich hässlich machen.

Verfasst: 31. März 2008 17:44
von RHBaum
Prinzipiell sollte man nie "events" direkt zeichnen lassen ....

in den meisten fallen ist die eine Aenderung in den "Daten" die soweiso im Memory liegen , performancetechnisch trivial ....
aus den Daten dann zeichen, also die drawroutinen an die Api schiessen ist hingegen meist sehr aufwendig ....

Deshalb sollten der Schritt von Daten zu Zeichenroutine nur dann gemacht werden, wenn noetig. Es macht kein sinn, ein bild 30000 mal in der Sekunde zu zeichnen .....
fuer statische zeichenungen, also dinge die keine bewegungsablaufe sind, reicht meist 2 oder 1 mal pro sekunde ... bei spielen sollt man 30 ned unterschreiten und alles uber 60 bringt nix wirklich .

Als guenstig hat sich bei uns erwiesen, nen timer(einstellbar) aufzuziehen, der schaut, ob sich ueberhaupt was geaendert hat.
Wenn nein, kein Problem. Wenn ja, den bereich ermitteln der ueberhaupt neu gezeichnet wird, und diesen bereich dann auf ungueltig (update) setzen .... um den rest kuemmert sich das BS eh.

Wenn es wirklich um figuren geht, loehnt es sich auch oft mittels optimierten funktionen in "unsichtbare Bilder" also speicherbereiche zu schreiben, und diese speicher an die Graka schicken lassen (wenn man kein renderer hat, klar).

Mit dem Aufbau der Daten, so das sie "leicht" zeichenbar sind, kann man auch ne menge optimieren ....

Ciao ....

Verfasst: 31. März 2008 17:47
von slash-ex
ich denke, mal das das datengerüst ganz gut funktioner und vorallem das problem darin liegt, das man viel unützes zeug zeichnet. deshalb werde ich wohl einen timer einsetzen.
Wenn es wirklich um figuren geht, loehnt es sich auch oft mittels optimierten funktionen in "unsichtbare Bilder" also speicherbereiche zu schreiben, und diese speicher an die Graka schicken lassen (wenn man kein renderer hat, klar).
wie genau schickst du das an die grafikkarte?

Verfasst: 31. März 2008 23:43
von slash-ex
angenommen ich habe eine qgraphicsscene und diese enthält einen background einen neu definierten foreground, der auf mauseingaben reagiert und items. jetzt wäre der plan, das bei einer mausbewegung nur der forground upgedatet werden soll, aber leider wird mit update() auch die paint()-fkt. der items aufgerufen.
wie kann man das umgehen?

Re: Zeichnen beschleunigen, aber wie?

Verfasst: 1. April 2008 07:50
von Uwe
slash-ex hat geschrieben:mir ist irgendwie aufgefallen, das die zeichengeschwindigkeit irgendwie langsam wird, vorallem wenn man den ausschnitt vergrößert.
Qt hat die unangenehme Eigenschaft, daß es Linien und Kurven vollständig rendert, bevor sie geclippt werden. D.h. wenn Du eine gepunktete Linie zeichnen willst, deren Endpunkte weit ausserhalb des sichtbaren Bereichs liegen ( z.B. wenn Du tief zoomst ) werden alle Punkte dieser Linie gerendert, auch wenn dann nur wenige tatsächlich gezeichnet werden. Der beschriebene Effekt hängt natürlich von der Position der Endpunkte und dem gewählten Linientyp ab, kann aber sehr drastisch sein.

Dagegen kannst Du eigentlich nur vorgehen indem Du das Clipping manuell selber durchführst. Ich mache das z.B. so in Qwt und wenn Du eine Implementierung für Polygon Clipping benötigst findest Du die in qwt_rect.cpp.

HTH,
Uwe

PS: Ich bin übrigens gerade selber dabei das Clipping für das Zeichnen von Kreisen zu implementieren, da das Zeichnen des Grids für das neue Qwt Polar Plot Widget nach dem Zoomen fürchterlich langsam wird.

Verfasst: 1. April 2008 11:43
von RHBaum
wie genau schickst du das an die grafikkarte?
Gar ned, wenn die Graka rendert .... funktioniert das natuerlich ned.

Das funktioniert nur, wenn Du selber "aufm speicher" zeichnest .....
Auf QT ebene: auf QPixmap direkt zeichnen ....
Du hasst dann also nen resultierendes Pixmap, was die QT einfach nur anzuzeigen braucht .... Die Pixmaps machen das bei der QT glaub ich sogar alleine, such mal unter double buffering ...

Ciao,