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 von

    Application->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?


Anmelden zum Antworten