Zeichnen beschleunigen, aber wie?

Alles rund um die Programmierung mit Qt
Antworten
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Zeichnen beschleunigen, aber wie?

Beitrag 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);
}
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag 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.
Zuletzt geändert von slash-ex am 31. März 2008 17:44, insgesamt 1-mal geändert.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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 ....
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag 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?
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag 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?
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Re: Zeichnen beschleunigen, aber wie?

Beitrag 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.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag 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,
Antworten