Seite 1 von 1

Wie wartet man bis QGLWidget komplett sichtbar ist

Verfasst: 23. September 2008 09:26
von dgray
Hallo an alle!

Ich suche nach einer einfachen Möglichkeit zu warten bis ein QGLWidget komplett sichtbar bzw. aktualisiert ist, um dann den framebuffer auslesen zu können.
Kurz zum Hintergrund: Ich möchte ein Mehr-Kamera-System mit simulieren.
Dazu habe ich eine (relativ einfache) statische 3D-Szene, die in meiner von QGLWidget abgeleiteten GLCam-Klasse kodiert ist. Jede Instanz von GLCam repräsentiert eine andere "virtuelle" Kamera, also anderer Standort bezügl. der Szene, andere Kameraparameter (wie z.B.Sensorgröße, Auflösung, Objektiv mit verschiedenen Brennweiten,Linsenverzeichnungsparametern usw.). Meine Anwendung braucht nun von jeder virtuellen Kamera eine Aufnahme. Mein Ansatz bisher:

for(int i=0; i<AnzKameras; ++i){
virtuelleKamera.raise();
virtuelleKamera.repaint();
/*
wünschenswert wäre so etwas wie die folgende Funktion
virtuelleKamera.ensureVisiblity();
*/
virtuelleKamera.grabFrameBuffer().save(QString("Bild_%i.png").arg(i));
}

funktioniert leider nicht, da anscheinend meine GLCam-Instanzen nicht mit dem Rendern der Szene hinterherkommen und die gespeicherten Bilder leer bleiben. activateWindow() oder show() von QGLWidget helfen leider auch nicht. Hat jemand ne Idee wie ich sowas einfach hinbekomme? Bzw. gibt es schon eine Funktion wie die oben im Kommentar stehende Funktion?

Vielen Dank schonmal und Grüße
DGray

Verfasst: 23. September 2008 11:55
von Volker
Hast du's statt mit repaint schon mal mit updateGL() probiert?

Verfasst: 23. September 2008 13:48
von dgray
virtuelleKamera.updateGL();

klappt leider auch nicht. :(

Ich als Laie erklaere mir das ganze so:
Die ganze Renderei und Fensteranzeigerei ueber OpenGL/Qt wird in einen extra Thread gepackt und von wem auch immer ausgefuehrt. Leider findet anscheinend beim grabFrameBuffer() kein Abgleich statt ob der Thread fertig ist oder nicht. Darum kann es anscheinend sein, dass noch kein Bild ausgelesen werden kann. (Im Uebrigen klappt mein obiger Ansatz fuer kleine Bilder (also simulierte Kamerabilder), aber wenn die Bilder groesser werden und die Berechnungen ueberhand nehmen nicht mehr.)
Irgendwo gibt es doch bestimmt ein Flag, welches anzeigt ob ein Fenster fertig gerendert ist oder nicht. Auf dieses Flag muesste ich dann mit dem grabFrameBuffer() warten. Leider weiss ich nicht wo ich dieses Flag finden kann.

Verfasst: 23. September 2008 13:54
von Volker
Nein ich glaube nicht, dass es in einem Extrathread gerendert wird. Wird paintGL aufgerufen wenn Du updateGL aufrufst? Wenn ja müsste soweit ich mich erinnere nach dem Aufruf von paintGL auch ein SwapBuffer Aufruf erfolgen, der eigentlich dafür sorgt, dass alle OpenGL Befehle fertig gerendert werden. Wenn Du kein Double Buffering verwendest, hilft evtl. ein glFlush oder glFinish

Verfasst: 23. September 2008 14:29
von dgray
Meine GLCam-Klasse implementiert die Funktion

paintEvent(QPaintEvent *event)

in welcher der ganze OpenGL-Kram gemacht wird. Und ganz am Ende dieser Funktion habe ich auch schon glFlush() bzw. glFinish() stehen. Klappt leider nicht :(

Verfasst: 23. September 2008 14:41
von Volker
GL Befehle sollten in der paintGL Methode implementiert werden.

Verfasst: 23. September 2008 15:18
von dgray
Volker hat geschrieben:GL Befehle sollten in der paintGL Methode implementiert werden.
Ich habe mich an das Trolltech-Beispiel:

http://doc.trolltech.com/4.4/opengl-overpainting.html

gehalten, weil ich die Overlays brauche, um einige Eigenschaften des virtuellen Kamerabildes zu simulieren. ( Da OpenGL nur lineare/linearisierbare Kameraprojektionen unterstuetzt, aber z.B. die Linsenverzerrung einer Kamera nicht mehr linear ist musste ich das ueber diesen Umweg machen ------> Es mag andere Moeglichkeiten geben, aber ich habe es nun mal so gemacht, weil mir das am einfachsten/bequemsten erschien. ).
Jedenfalls wird dort statt paintGL() auch paintEvent() implementiert.