7 Displaylisten

OpenGL ist im Normall eine „Immediate Mode State Machine", d.h. alle Kommandos werden sofort abgesetzt und zei-gen sofort Wirkung. Das heißt jedoch nicht, daß die Kommandos auch sofort eine Wirkung am Bildschirm zeigen ( Ser-ver - Clientmode ). Setzt man z.B. eine neue Zeichenfarbe oder hängt eine neue Transformationsmatrix an, so treten die Änderungen sofort in Kraft. Und das ist auch gut so.

7.1 Objektlisten

In vielen virtuellen Welten trifft man auf ein ähnliches Szenario. Mehrere Objekte bewegen sich durch eine nicht beweg-liche Landschaft und freuen sich ihres ( virtuellen ) Lebens. 90 Prozent der Welt sind unbeweglich. Warum sollte man also bei jedem Durchgang die gesamte Welt neu definieren. Und selbst die meisten beweglichen Objekte bewegen sich nur relativ zur Umgebung ( Translation, Rotation, usw. ) behalten aber ihr Aussehen.

Nun liegt die Idee nahe, die Umgebung und die Objekte nur einmal zu definieren und sie danach nur mehr ( an verschie-denen Positionen, mit unterschiedlicher Rotation, etc. ) darzustellen.

Genau das ermöglichen Displaylisten.

Die Vorgehensweise ist dabei ganz einfach: Man fordert eine freie Liste an, startet einen Aufzeichnungsmodus, sendet Kommandos, schließt die Liste und ruft sie dann auf.

Bei der Aufzeichnung stehen zwei Modi zu Verfügung:

Generell sieht eine Listenerstellung so aus:

// öffnet eine neu Liste im NUR-GENERIEREN-Modus
glNewList ( x, GL_COMPILE );
        .          // OpenGL - Kommandos
        .
        .
glEndList();       // Liste ist fertig

glCallList ( x );  // Liste ausführen

Für x bei glNewList() setzt man eine eindeutige Nummer ein, mit der man die Liste identifiziert. Verwendet man mehre-re Listen sollte man Listennummern anfordern ( ähnlich einem malloc o.ä. ). Dies geschieht mittels glGenList ( num ). Dies liefert den ersten der aufeinanderfolgenden Indizes.

// 10 Listen beginnend bei ListIndex
listIndex = glGenList ( 10 );
Das Besondere an Displaylisten ist folgendes: OpenGL ‘merkt’ sich die Kommandos die zwischen glNewList und glEndList abgesetzt wurden, aber nicht die tatsächlichen Befehle, sondern die Wirkung die die Befehle hatten. Man kann zur Erzeugung einer Displayliste auch komplexe Berechnung in C durchführen, etc. All dies merkt sich OpenGL aber nicht, sondern nur das Ergebnis.

Will man z.B. eine komplizierte Splinefläche in einer Displayliste definieren, und berechnet sich nach und nach in den Variablen x, y und z die Werte der Vertices, und gibt diese innerhalb der Liste mit glVertex(x,y,z) an, merkt sich OpenGL nur den Wert der Variablen. Es merkt sich nicht, daß das die Variablen x y z waren. Wenn man die Variablen nachträglich ändert, hat das keinerlei Änderung der Displayliste zur Folge. Es zählt lediglich der Wert der Variable zum Zeitpunkt der Listenerzeugung.

Manche OpenGL Implementierungen gehen sogar noch einen Schritt weiter und wenden einfache Optimierungen bei der Listenerzeugung an (z.B. Umwandlung in ein schnelleres internes Format oder dgl.).

Da sich OpenGL den Wert der Variablen merkt, und nicht die transformierten Werte, kann man Displaylisten wie ge-wohnt mit Matrizen transformieren.

All diesen Komfort bezahlt man allerdings mit der Tatsache, daß Displaylisten eine menge Speicher brauchen.

7.2 Listen zur Schrifterzeugung

Da wie bereits erwähnt in OpenGL standardmäßig keine Fontunterstützung ( weder True-Type noch Bitmap-Fonts ) implementiert ist, greift man auf die Möglichkeit zurück, mehrere Displaylisten auf einmal aufzurufen. Man definiert für jeden Buchstaben eine eigene Displayliste, erstellt ein Array, in dem jeder Eintrag eine Displaylisten-Nummer enthält ( im Normalfall einfach ein Array of char ), und benutzt dieses Array, um mehrere Listen auf einmal auszugeben.

glCallLists ( n, type, *lists )
ruft listen vom Typ auf. Die Listenindizes stehen an der Adresse .

definiert, welcher Datentyp dem Array zugrunde liegt. Zur Wahl stehen GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT, GL_INT oder GL_UNSIGNED_INT. Für die Textausgabe ist natürlich GL_UNSIGNED_BYTE anzuwenden.

Somit erreicht man, daß für jeden Buchstaben im String die entsprechende Displayliste aufgerufen wird , d.h. bei dem String „HALLO" werden die Listen mit Index 72, 65, 76, 76, 79 aufgerufen.

Auf diese Art und Weise kann man jedoch nur eine Schriftart verwenden, denn über das Zeichen „A" kann eben nur die Liste 65 aufgerufen werden, die die Zeichenbefehle für den Buchstaben „A" in einer bestimmten Schriftart enthält.

Zu diesem Zweck gibt es den Befehl glListBase ( basis ), der den Basisindex für folgende glCallLists-Aufrufe enthält. Setzt man den Basisindex z.B. auf 1000, wird durch den nachfolgenden Aufruf von glCallLists(5, GL_UNSIGNED_BYTE, „HALLO") die Listen mit Index 1072, 1065, 1076, 1076 und 1079 aufgerufen.

Eine Liste für einen Buchstaben muß neben den eigentlichen Zeichnen eines Buchstaben auch den Zeichencursor so setzen, daß das nächste Zeichen daneben gezeichnet wird ( glTranslate ).