OpenGL.org [Home] - [News & more] - [Netzwerk-Technik] - [3D-Technik] - [Download] - [Links] Linux-Counter
[3D-Mathe] - [3D-Grundlagen] - [3D-Hard- u. Software] - [OpenGL] - [OpenGL FAQ]

4 GLU

4.010 Was ist GLU ? Wo ist der Unterschied zu OpenGL ?

Man kann sich die OpenGL Basisbibliothek als Low Level 3D Grafikbibliothek vorstellen (prozedural, als Grundkörper sind nur Punkte und Linien bekannt). Darauf aufsetzend bildet die GLU den ersten Schritt zum deskritiven Grafiksystem, da hiermit schon komplexere Grundkörper definiert werden (Kugel, Zylinder etc.). Einige Funktionen der GLU sind:

Die besten Informationen über die GLU bieten das Red Book und Blue Book sowie die GLU Spezifikation ( auf der OpenGL Webseite).

4.020 Wie zeichnet die GLU Kugeln, Zylinder und Scheiben ?

Eigentlich gibt es hierbei keine Besonderheiten. Man kann die GLU Körper auch problemlos selbst nachbilden. Z. B. im Mesa Source Code kann die dort gefundene Lösung nachvollzogen werden.

Die GLU nutzt die Grundfunktionen der OpenGL, wie Triangle oder Quad Strips, um ihre Körper darzustellen. Die endgültige Form und der damit verbundene Aufwand kann über Parameter eingestellt werden, die interne Berechung der Punkte erfolgt dann über sinf() und cosf() der Mathebibliothek.

Um Zylinder oder offene Rohre zu zeichnen, kann auch die GLE Bibliothek als Hilfe genutzt werden. Sie ist Teil der GLUT Distribution.

4.030 Wie arbeitet gluPickMatrix() ?

Diese Funktion rechnet über Translate und Scale die selektierte Region so um, dass diese den gesamten Viewport ausfüllt.

    gluPickMatrix(centerX, centerY, breite, hoehe, viewport);

Wird die Funktion auf den Projektionsstack ( glMatrixMode(GL_PROJECTION); ) angewendet und vor dem Projektionsbefehl ( gluPerspective(), glFrustum() ) aufgerufen, wird das aktuelle Viewing Volumen auf den selektierten Bereich festgelegt. In diesem Fall wird jedes Objekt, das auch nur teilweise in den selektierten Bereich fällt, als innerhalb des Viewing Volumens angesehen. Mit glRenderMode(GL_SELECT) werden diese Objekte an den Aufrufer zurückgegeben.

4.040 Wie kann ich die Funktionen der Tesselation nutzen ?

Die GLU bietet Funktionen, um konkave Polygone (die Verbindungslinien zweier beliebiger Eckpunkte schneiden eine andere Verbindungslinie) und Polygone mit einem inneren Hohlraum richtig darzustellen. Die Grundfunktionen der OpenGL benötigen in jedem Fall konvexe Polygone. Die Tesselation Funktion der GLU bricht diese Polygone so auf, dass sie korrekt durch die OpenGL dargestellt werden können (hinzufügen von Punkten, Aufsplitten in mehrere Polygone etc.). Dies geschieht, indem man Tesselation Callbacks für die entsprechenden Primitive festlegt, die automatisch aufgerufen werden und die vereinfachten Daten an die OpenGL übergeben. Im Quellcode selbst werden normale OpenGL Funktionen zum Zeichnen genutzt.

Ein Beispielprogramm findet man im GLUT Quellcode unter progs/redbook/tess.c.

Das Vorgehen zum Nutzen der Tesselation ist wie folgt:

  1. neues GLU Tesselation Objekt anlegen
          GLUtesselator *tess = gluNewTess();
  2. Callbacks festlegen
          gluTessCallback (tess, GLU_TESS_BEGIN, tcbBegin);
          gluTessCallback (tess, GLU_TESS_VERTEX, tcbVertex);
          gluTessCallback (tess, GLU_TESS_END, tcbEnd);
    Falls sich Verbindungslinien des Polygons schneiden, muss auch ein Callback zum Erzeugen zusätzlicher Eckpunkte festgelegt werden
          gluTessCallback (tess, GLU_TESS_COMBINE, tcbCombine);
  3. Das Senden der Daten an die GLU realisiert man so:
          // im Vorfeld angelegt und mit passenden Daten versehen wurde dieses Feld:
          // GLdouble data[numVerts][3];
          gluTessBeginPolygon (tess, NULL);
          gluTessBeginContour (tess);
          for (i=0; i<sizeof(data)/(sizeof(GLdouble)*3);i++)
            gluTessVertex (tess, data[i], data[i]);
          gluTessEndContour (tess);
          gluEndPolygon (tess);
  4. In den Callbacks sind folgende OpenGL Aufrufe vorzunehmen:
          void tcbBegin (GLenum prim);
          {
            glBegin (prim);
          }
    
          void tcbVertex (void *data)
          {
            glVertex3dv ((GLdouble *)data);
          }
    
          void tcbEnd ();
          {
            glEnd ();
          }
    
          void tcbCombine (GLdouble c[3], void *d[4], GLfloat w[4], void **out)
          {
            GLdouble *nv = (GLdouble *) malloc(sizeof(GLdouble)*3);
    
            nv[0] = c[0];
            nv[1] = c[1];
            nv[2] = c[2];
            *out = nv; 
          }

Die vorangegangene Liste stellt nur ein vereinfachtes Beispiel dar, demonstriert also noch nicht den vollen Funktionsumfang der OpenGL. Durch die Übergabe der Daten an gluTessBeginPolygon() und gluTessVertex() sowie die Festlegung der Callbacks kann das Programm diese Polygone wie jedes andere behandeln, also auch Farben und Texturen wie üblich nutzen.

4.050 Warum werden meine Tesselation-Callbacks nicht aufgerufen ?

Normalerweise werden die Tesselation Callbacks nach gluEndPolygon() ausgeführt. Falls das nicht funktioniert, ist irgendwo ein Fehler aufgetreten. Eine typische Ursache liegt im Fehlen vom GLU_TESS_COMBINE* Callback, der für die Bearbeitung konkaver (self-intersecting) Polygone notwendig ist.

Es kann auch ein Callback für GLU_TESS_ERROR definiert werden, der auftretende Fehler meldet.

4.060 Wie kann ich die NURBS-Funktionen nutzen ?

Die GLU NURBS Schnittstelle konvertiert die B-Spline Basiskontrollpunkte in Kontrollpunkte für Bezierkurven und übergibt diese an die OpenGL Evaluator Funktionen. Diese zeichnen dann die Oberfläche.

Ein Beispielprogramm ist z.B. in der GLUT Distribution unter progs/redbook/surface.c verfügbar.

4.070 Wie arbeite ich mit gluProject und gluUnProject ?

Beide Funktionen nutzt die ModelView- und Projektionsmatrix und den OpenGL Viewport als vorzugebende Parameter.

    gluProject(objX, objY, objZ,
               modelMatrix, projMatrix, viewport,
               &winX, &winY, &winZ);

    gluUnProject(winX, winY, winZ,
                 modelMatrix, projMatrix, viewport,
                 &objX, &objY, &objZ);

gluProject() benönigt darüber hinaus auch eine XYZ-Koordinate des Modellkoordinatensystems (objX, objY, objZ), aus denen die XYZ-Bildschirmkoordinate berechnet und zurückgegeben wird (winX, winY, winZ).

gluUnProject() geht den umgekehrten Weg. Aus der übergebenen XYZ-Bildschirmkoordinate wird die entsprechende Modellkoordinate berechnet und zurückgegeben.

Das Konzept der Z-Bildschirmkoordinate ist auf den ersten Blick etwas verwirrend, da der Monitor ja ein nur zweidimensionales Ausgabegerät ist. Die Z-Koordinate stellt hier aber den Wert des Tiefenbuffers als GLdouble (zwischen 0.0 - 1.0) dar, zeigt also die Lage des Objektes relativ zum Viewport. Hat man mit glDepthRange() den Tiefenbuffer nicht beeinflusst, entspricht ein Z-Wert von 0.0 der Lage des Objekts am vorderen Rand des Viewports (zNear) bzw. ein Wert von 1.0 den hinteren Rand (zFar). Mit glReadPixels() lässt sich auch der Z-Wert an jeder beliebigen Koordinate ermitteln.

[zum Seitenanfang] Fragen oder Ideen an: Thomas.Kern@3Dsource.de [zur Startseite]
(C) Thomas Kern .