Refresh einer Anzeige
-
Hallo zusammen,
ich habe, um eine visuelle Ergebniskontrolle zu ermöglichen, ein Formular in mein Prog eingefügt, auf dem mittels OpenGL eine 3D-Szene dargestellt wird. Dies besteht aus 12 Dreiecken und ca 20 Linien. Ich verwende den BCB6.
Jetzt habe ich die folgenden beiden Probleme, bei denen ich nicht weiter weiss:
Während des Programmablaufs wird die Szene 100 mal vollständig neu konstruiert. Dies dauert insgesamt weniger als drei Sekunden. Leider wird die Anzeige nur drei mal aktualisiert. Auch wenn ich den Rechner zwischen jedem Durchlauf für eine halbe Sekunde aussetzen lasse, werden nur etwa die Hälfte der Bilder dargestellt.
Ich verwende nach der Neukonstruktion der Szene den folgenden Code:
if (UseDoubleBuffer) SwapBuffers(dc); else glFlush();
Dieser sollte eigentlich die Anzeige aktualisieren. (Steht zumindest in meinem Buch...)
Auch der Einsatz vonApplication->ProcessMessages()
bringt nichts. Wenn ich
Form->Repaint()
aufrufe, flackert das Fenster zwar 100mal, sonst ändert sich leider nichts. Und nach dem letzten Aufruf von Repaint ist die 3D-Szene weg.
Das zweite Problem ist, dass die Szene, nach dem das Formular überdeckt wurde, verschwunden ist sich zudem nicht an eine veränderte Fenstergröße anpasst. (Obwohl bei einem Resize-Ereignis die Szene neu gezeichnet wird.
In welcher Richtung liegt die Lösung? Kann mir jemand helfen?
Vielen Dank schon mal.
Gruß,
chris_f
-
Bei Deinen Infos kann man nicht viel mehr sagen als "Du hast Mist gebaut!".
Vielleicht etwas Quellcode oder so?!?
-
Ok, einverstanden.
Nachdem ich zum ersten mal mit OpenGL arbeite und meine Unterlagen sehr begrenzt sind, weiß ich nicht was wichtig ist. Also tu ich mal alles posten...Dies ist der gesamte Code, den ich zu der Anzeige gemacht habe (bzw. abgeschrieben habe). Die Geometriedaten sind in zwei Vektoren hinterlegt, die ich zwischen den einzelnen Aufrufen mit neuen Daten füttere.
Wenn diese Daten bereit stehen, rufe ich die Funktion DrawScene (ganz unten) auf. Am Ende der Funktion sollte dann die Szene eigentlich aktualisiert werden.#include <vcl.h> #pragma hdrstop #include "Start.h" #include <gl\gl.h> #include <gl\glu.h> #include "Visualisierung.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TFormOpenGL *FormOpenGL; //--------------------------------------------------------------------------- __fastcall TFormOpenGL::TFormOpenGL(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TFormOpenGL::FormCreate(TObject *Sender) { UseDoubleBuffer = true; if(StartForm->CBBild->Checked) { FormOpenGL->Visible = true; } // Diese Codesequenz habe ich übernommen. Der Inhalt ist mir nur zum Teil klar dc = InitOpenGL(FormOpenGL->Handle,UseDoubleBuffer); glEnable(GL_DEPTH_TEST); // notwendig für Tiefenpuffer glClearColor(1, 1, 1, 1); // Hintergrund weiß glMatrixMode(GL_MODELVIEW); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel (GL_FLAT); glLineWidth(3); } //--------------------------------------------------------------------------- // Diese Funktion habe ich ebenfalls abgeschrieben HDC TFormOpenGL::InitOpenGL(HWND Handle,bool UseDoubleBuffer) { PIXELFORMATDESCRIPTOR pfd; memset(&pfd,0,sizeof(pfd)); // setze alle Felder auf 0 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; // Versionsnummer, 1 notwendig pfd.dwFlags = // Eigenschaften des Pixelpuffers PFD_DRAW_TO_WINDOW | // Zeichne in ein Fenster PFD_SUPPORT_OPENGL; // OpenGL anstelle von GDI if (UseDoubleBuffer)// Doppelbuffer verwenden pfd.dwFlags |= PFD_DOUBLEBUFFER; // flag setzen pfd.iPixelType = PFD_TYPE_RGBA; // RGBA Pixel pfd.cColorBits = 24; // Farbtiefe 24 Bit pfd.cDepthBits = 32; // Tiefenpuffer 32 Bits pfd.iLayerType = PFD_MAIN_PLANE; // Einzige Möglichkeit HDC dc = GetDC(Handle); int iPF = ChoosePixelFormat(dc, &pfd); if (iPF==0) ShowMessage("Fehler bei ChoosePixelFormat"); SetPixelFormat(dc, iPF, &pfd ); GLContext = wglCreateContext(dc); if (GLContext) wglMakeCurrent(dc, GLContext); else ShowMessage("wglMakeCurrent nicht erfolgreich"); return dc; } //--------------------------------------------------------------------------- // Diese Funktion habe ich ebenfalls abgeschrieben void __fastcall TFormOpenGL::FormDestroy(TObject *Sender) { ReleaseDC(Handle,dc); wglMakeCurrent(dc, NULL); wglDeleteContext(GLContext); } //--------------------------------------------------------------------------- void __fastcall TFormOpenGL::FormResize(TObject *Sender) { // um Aufruf des Codes von anderer Stelle zu vereinfachen, auslagern in // hilfsfunktion. (siehe unten) void hilfsfunktion(); } //--------------------------------------------------------------------------- void TFormOpenGL::hilfsfunktion() { static GLfloat transx = 0; static GLfloat transy = 0; static GLfloat transz = 0; static GLfloat rotx = 0; static GLfloat roty = 0; static GLfloat rotz = 0; // Diesen Teil habe ich ebenfalls abgeschrieben glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLdouble aspect =(double)ClientWidth/ClientHeight; gluPerspective(60, aspect, 1, 10000); glMatrixMode(GL_MODELVIEW); // Positionierung der Anzeige gemäß der Eingabe einer einfachen GUI-Schnittstelle glTranslated((StartForm->SETransX->Value - transx), (StartForm->SETransY->Value - transy), (StartForm->SETransZ->Value - transz)); transx = StartForm->SETransX->Value; transy = StartForm->SETransY->Value; transz = StartForm->SETransZ->Value; glRotated((StartForm->SERotX->Value - rotx), 1, 0, 0); glRotated((StartForm->SERotY->Value - roty), 0, 1, 0); glRotated((StartForm->SERotZ->Value - rotz), 0, 0, 1); rotx = StartForm->SERotX->Value; roty = StartForm->SERotY->Value; rotz = StartForm->SERotZ->Value; DrawScene(); } //--------------------------------------------------------------------------- void TFormOpenGL::DrawScene() { // Diese Zeile habe ich ebenfalls abgeschrieben glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Dreiecke der Geometrie zeichnen GLfloat colRed[] = {1, 0, 0, 0.5}; GLfloat colBlack[] = {0, 0, 0}; unsigned int zaehler1 = 0; glBegin(GL_LINES); for(zaehler1 = 0; zaehler1 != StartForm->NeuStaebe.size(); zaehler1++) { glColor3fv(colBlack); glVertex3d(StartForm->NeuKnoten[StartForm->NeuStaebe[zaehler1].a].x, StartForm->NeuKnoten[StartForm->NeuStaebe[zaehler1].a].y, StartForm->NeuKnoten[StartForm->NeuStaebe[zaehler1].a].z); glVertex3d(StartForm->NeuKnoten[StartForm->NeuStaebe[zaehler1].b].x, StartForm->NeuKnoten[StartForm->NeuStaebe[zaehler1].b].y, StartForm->NeuKnoten[StartForm->NeuStaebe[zaehler1].b].z); } glEnd(); glBegin(GL_TRIANGLES); for(zaehler1 = 0; zaehler1 != StartForm->Koerper.size(); zaehler1++) { glColor4fv(colRed); glVertex3d(StartForm->Koerper[zaehler1].ax, StartForm->Koerper[zaehler1].ay, StartForm->Koerper[zaehler1].az); glVertex3d(StartForm->Koerper[zaehler1].bx, StartForm->Koerper[zaehler1].by, StartForm->Koerper[zaehler1].bz); glVertex3d(StartForm->Koerper[zaehler1].cx, StartForm->Koerper[zaehler1].cy, StartForm->Koerper[zaehler1].cz); } glEnd(); // HIER AN DIESER STELLE VERMUTE ICH DAS PROBLEM. // Anzeige aktualisieren if (UseDoubleBuffer) SwapBuffers(dc); else glFlush(); }
Ich hoffe ich habe euch damit nicht erschlagen.
Gruß,
chris_f
-
*push*
Ich finde selbst leider keine Lösung.
Kann mir bitte jemand helfen?