NeHe - Lektion 09 - Bitmaps in einer 3D-Umgebung bewegen

Lektion 9



Willkommen zu Tutorial 9. Sie sollten nun ein sehr gutes Veständnis von OpenGL haben. Sie haben gelernt, wie man ein OpenGL Fenster erzeugt, wie man rotierende Objekte texturiert während Beleuchtung und Bleding verwendet werden. Das wird das erste halb-fortgeschrittene Tutorial. Sie werden folgendes lernen: Bitmaps in 3D bewegen, die schwarzen Pixel um das Bitmap herum entfernen (indem Blending verwendet wird), Farben zu einer schwarz-weiß Textur hinzufügen und letztlich werden Sie lernen, wie man eindrucksvolle Farben und einfache Animationen erzeugt, indem man verschieden farbige Texturen mischt.

Wir werden den Code aus der letzten Lektion dafür modifizieren. Wir fangen an, ein paar neue Variablen am Anfang des Programms einzufügen. Ich schreibe den kompletten Abschnitt des Codes noch mal hin, damit es einfacher zu sehen ist, welche Änderungen vorgenommen wurden.

#include    <windows.h>                    // Header Datei für Windows
#include    <stdio.h>                    // Header Datei für Standard Ein-/Ausgabe
#include    <gl\gl.h>                    // Header Datei für die OpenGL32 Library
#include    <gl\glu.h>                    // Header Datei für die GLu32 Library
#include    <gl\glaux.h>                    // Header Datei für die GLaux Library

HDC        hDC=NULL;                    // Privater GDI Device Context
HGLRC        hRC=NULL;                    // Permanenter Rendering Context
HWND        hWnd=NULL;                    // Enthält unser Fenster-Handle
HINSTANCE    hInstance;                    // Enthält die Instanz der Applikation

bool        keys[256];                    // Array das für die Tastatur Routine verwendet wird
bool        active=TRUE;                    // Fenster Aktiv Flag standardmäßig auf TRUE gesetzt
bool        fullscreen=TRUE;                // Fullscreen Flag ist standardmäßig auf TRUE gesetzt

Die folgenden Zeilen sind neu. twinkle und tp sind BOOLische Variable, was bedeutet, dass Sie TRUE oder FALSE sein können. twinkle gibt an, ob der Glitzer-Effekt aktiviert wurde. tp wird benutzt, um zu überprüfen, ob die Taste 'T' gedrückt oder losgelassen wurde (gedrückt tp=TRUE, losgelassen tp=FALSE).

BOOL    twinkle;                        // glitzernde Sterne
BOOL    tp;                            // Taste 'T' gedrückt?

num enthält die Anzahl der zu zeichnenden Sterne. Diese ist als CONSTant definiert. Das bedeutet, dass sie niemals innerhalb des Codes geändert werden kann. Der Grund, warum wir die Anzahl als konstant definieren ist der, dass wir kein Array re-definieren können. Wenn wir also ein Array für nur 50 Sterne initialisieren und wir uns entscheiden num irgendwo im Code auf 51 zu erhöhen, kann das Array nicht auf 51 anwachsen und ein Fehler würde auftreten. Sie können diesen Wert auf jeglichen gewünschten Wert ändern, aber nur in dieser Zeile. Versuchen Sie nicht den Wert von num später im Code zu ändern, es sei denn, Sie wollen das ein Unglück passiert.

const    num=50;                            // Anzahl der zu zeichnenden Sterne

Nun erzeugen wir eine Struktur. Das Wort Struktur klingt einschüchternd, ist es aber nicht wirklich. Eine Struktur ist eine Gruppe einfacher Daten (Variablen, etc.), die zusammen eine große Gruppe repräsentieren. Auf deutsch :) Wir wissen, dass wir die Sterne kontrolliere. Sie sehen, dass die 7te Zeile stars; lautet. Wir wissen, dass jeder Stern 3 Werte für Farbe haben wird und all diese Werte werden Integers sein. Die 3te Zeile int r,g,b deklariert 3 Integer Werte. Einen für Rot (r), einen für Grün (g) und einen für Blau (b). Wir wissen, dass jeder Stern eine andere Distanz vom Mittelpunkt des Screens haben wird und an einen von 360 verschiedenen Winkeln vom Zentrum aus gesetzt werden kann. Wenn Sie sich die 4te Zeile anschauen, haben wir dort einen Fließkommawert names dist. Dieser enthält die Distanz. Die 5te Zeile erzeugt einen Fließkommawert names angle. Dieser enthält den Winkel der Sterne.

So, nun haben wir diese Gruppe von Daten, die die Farbe, Distanz und Winkel des Sterns auf dem Screen beschreiben. Unglücklicherweise haben wir mehr als ein Stern, den wir kontrollieren. Anstatt 50 Rot-Werte, 50 Grün-Werte, 50 Blau-Werte, 50 Distanz-Werte und 50 Winkel-Werte zu erzeugen, erzeugen wir einfach ein Array names star. Jede Zahl in dem star Array wird all diese Informationen enthalten und zwar in unserer Struktur namens stars. Wir erzeugen das star Array in der 8ten Zeile. Sie lautet: stars star[num]. Damit haben wir angefangen. Die Art des Arrays wird also vom Typen stars sein. Stars ist eine Struktur. Die Anzahl der Strukturen (bzw. die Array-Größe) ist [num]. Da num=50 ist, haben wir nun ein Array names star. Unser Array speichert die Elemente der Struktur stars. Das ist wesentlich einfacher, als jeden einzelnen Stern mit seperaten Variablen zu kontrollieren. Außerdem wäre das ziemlich blöde zu realisieren und würde es uns nicht erlauben, Sterne hinzuzufügen oder zu entfernen, indem wir den konstanten Wert von num ändern.

typedef struct                            // erzeugt eine Struktur für einen Stern
{
    int r, g, b;                        // Stern Farbe
    GLfloat dist;                        // Stern Entfernung vom Mittelpunkt
    GLfloat angle;                        // aktueller Winkel des Sterns
}
stars;                                // Strukturname ist Stars
stars star[num];                        // erzeuge ein 'star' Array mit 'num' Elementen und benutze die Informationen aus der Struktur 'stars'

Als nächstes führen wir Variablen ein, die die Entfernung der Sterne zum Betrachter (Zoom) enthalten und von welchem Winkel wir die Sterne aus sehen (tilt). Wir erzeugen eine Variable namens spin, welche die glitzernden Sterne auf der Z-Achse rotieren lassen wird, was sie aussehen lassen wird, als wenn Sie auf der Stelle rotieren würden.

loop ist eine Variable, die wir zum Zeichnen aller 50 Sterne verwenden werden und texture[1] wird benutzt um die schwarz-weiß Textur zu speichern, die wir laden werden. Wenn Sie mehr Texturen haben wollen, erhöhen Sie den Wert von eins auf die Anzahl der Texturen, die Sie verwenden wollen.

GLfloat    zoom=-15.0f;                        // Betrachtungs-Entfernung der Sterne
GLfloat tilt=90.0f;                        // Kippt die Ansicht
GLfloat    spin;                            // rotiert glitzernde Sterne

GLuint    loop;                            // Generelle Schleifen Variable
GLuint    texture[1];                        // Speicherplatz für eine Textur

LRESULT    CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);        // Dellaration für WndProc

Direkt hinter der letzten oberen Zeile, fügen wir den Code zum Laden unserer Textur ein. Ich brauche den Code nicht großartig im Detail erklären. Es ist der selbe Code, den wir zum Laden der Texturen in den Lektionen 6, 7 und 8 verwendet haben. Das Bitmap, welches wir diesmal laden, heißt star.bmp. Wir erzeugen nur eine Textur mittels glGenTextures(1, &texture[0]). Die Textur wird linearen Filter verwenden.

AUX_RGBImageRec *LoadBMP(char *Filename)            // Lädt ein Bitmap
{
    FILE *File=NULL;                    // Datei Handle

    if (!Filename)                        // gehe sicher, dass ein Dateiname übergeben wurde
    {
        return NULL;                    // wenn nicht, gebe NULL zurück
    }

    File=fopen(Filename,"r");                // gehe sicher, dass ein Dateiname übergeben wurde

    if (File)                        // überprüfe, ob die Datei existiert.
    {
        fclose(File);                    // Schließe das Handle
        return auxDIBImageLoad(Filename);        // Lädt das Bitmap und gibt einen Zeiger zurück
    }
    return NULL;                        // Wenn das Laden fehl schlug, gebe NULL zurück
}

Das ist der Codeabschnitt, welcher das Bitmap lädt (indem der obige Code aufgerufen wird) und es in eine Textur konvertiert. Status wird verwendet, um zu verfolgen, ob die Textur geladen und erzeugt wurde oder nicht.

int LoadGLTextures()                        // Lade Bitmaps und konvertiere in Texturen
{
    int Status=FALSE;                    // Status Indikator

    AUX_RGBImageRec *TextureImage[1];            // erzeuge Speicherplatz für die Textur

    memset(TextureImage,0,sizeof(void *)*1);        // Setze den Zeiger auf NULL

    // Lade das Bitmap, prüfe auf Fehler, wenn Bitmap nicht gefunden wurde, beende
    if (TextureImage[0]=LoadBMP("Data/Star.bmp"))
    {
        Status=TRUE;                    // Setze Status auf TRUE

        glGenTextures(1, &texture[0]);            // erzeuge eine Textur

        // erzeuge linear gefilterte Textur
        glBindTexture(GL_TEXTURE_2D, texture[0]);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
    }

    if (TextureImage[0])                    // Wenn Textur existiert
    {
        if (TextureImage[0]->data)            // Wenn Textur-Bild existiert
        {
            free(TextureImage[0]->data);        // Gebe den Textur Image Speicher frei
        }

        free(TextureImage[0]);                // gebe die Image-Struktur frei
    }

    return Status;                        // gebe den Status zurück
}

Nun initialisieren wir OpenGL so, dass auf die Art gerendert wird, wie wir es wünschen. Wir werden den Depth Test in diesem Projekt nicht verwenden, stellen Sie also sicher, wenn Sie den Code aus Lektion eins verwenden, dass Sie glDepthFunc(GL_LEQUAL); und glEnable(GL_DEPTH_TEST); entfernen, da Sie ansonsten ein paar unschöne Ergebnisse erhalten werden. Wir werden Textur Mapping in diesem Code verwenden, weshalb Sie sicher stellen sollten, alle fehlenden Zeilen, die nicht in Lektion 1 vorkamen, hinzuzufügen. Sie werden feststellen, dass wir Textur Mapping zusammen mit Blending aktivieren.

int InitGL(GLvoid)                        // Der ganze Setup Kram für OpenGL kommt hier rein
{
    if (!LoadGLTextures())                    // Rufe Textur Lade Routine auf 
    {
        return FALSE;                    // wenn Textur nicht geladen wurde, gebe FALSE zurück 
    }

    glEnable(GL_TEXTURE_2D);                // aktiviere Textur Mapping 
    glShadeModel(GL_SMOOTH);                // aktiviere Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);            // schwarzer Hintergrund
    glClearDepth(1.0f);                    // Depth Buffer initialisieren
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // wirklich nette Perspektiven Berechnungen
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);            // Setze die Blending Funktion für Dursichtigkeit
    glEnable(GL_BLEND);                    // aktiviere Blending

Der folgende Code ist neu. Er initialisiert den Anfangs-Winkel, Distanz und Farbe jeden Sterns. Beachten Sie, wie einfach es ist, die Informationen der Struktur zu verändern. Die Schleife durchläuft alle 50 Sterne. Um den Winkel von Star[1] zu ändern, müssen wir lediglich star[1].angle={irgend eine Zahl} schreiben. So einfach ist das!

    for (loop=0; loop<num; loop++)                // erzeuge eine Schleife, die alle Sterne durchläuft
    {
        star[loop].angle=0.0f;                // Alle Sterne haben am Anfang den Winkel 0

Ich berechne die Distanz indem ich den aktuellen Stern nehme (was dem Wert von loop entspricht) und dividiere ihn mit der maximalen Anzahl an Sternen. Dann multipliziere ich das Ergebnis mit 5.0f. Das bewegt jeden Stern etwas weiter als den vorherigen Stern. Wenn loop gleich 50 ist (der letzte Stern), loop dividiert durch num wird 1.0f ergeben. Der Grund warum ich mit 5.0f multipliziere ist, dass 1.0f*5.0f gleich 5.0f ist. 5.0f ist die äußerste Kante unseres Screens. Ich möchte nicht, dass Sterne vom Screen verschwinden, weshalb 5.0f also perfekt ist. Wenn Sie den Zoom weiter in den Screen hinein setzen, können Sie einen höheren Wert als 5.0f verwenden, aber Ihre Sterne wären um ein vielfaches kleiner (auf Grund der Perspektive).

Sie werden feststellen, dass die Farbe für jeden Stern auf einen Zufallswert zwischen 0 und 255 basiert. Sie werden sich fragen, warum wir so große Werte verwenden können, wenn die Farben normalerweise zwischen 0.0f und 1.0f liegen. Wenn wir die Farbe setzen, verwenden wir glColor4ub anstatt glColor4f. ub heißt Unsigned Byte (vorzeichenloses Byte). Ein Byte kann jeden Wert zwischen 0 und 255 annehmen. In diesem Programm ist es einfach Bytes zu verwenden, als zufallsgenerierte Fließkommawerte.

        star[loop].dist=(float(loop)/num)*5.0f;        // berechne die Distanz vom Mittelpunkt 
        star[loop].r=rand()%256;            // weise star[loop] eine zufällige Rot-Intensität zu
        star[loop].g=rand()%256;            // weise star[loop] eine zufällige Grün-Intensität zu
        star[loop].b=rand()%256;            // weise star[loop] eine zufällige Blau-Intensität zu
    }
    return TRUE;                        // Initialisierung war OK
}

Da der Resize-Code der selbe ist, kommen wir zum Zeichnen-Code. Wenn Sie den Code aus Lektion eins verwenden, löschen Sie den DrawGLScene Code und kopieren Sie folgenden Code hinein. Es gibt sowieso nur 2 Codezeilen aus Lektion eins, weshalb es auch nicht so viel zum löschen gibt.

int DrawGLScene(GLvoid)                        // Hier kommt der ganze Zeichnen-Kram hin

{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // Lösche den Bildschirm und den Depth-Buffer
    glBindTexture(GL_TEXTURE_2D, texture[0]);        // wähle unsere Textur aus

    for (loop=0; loop<num; loop++)                // durchlaufe alle Sterne
    {
        glLoadIdentity();                // Resette die View bevor wir jeden einzelnen Stern zeichnen
        glTranslatef(0.0f,0.0f,zoom);            // Zoom in den Screen hinein (indem der Wert aus 'zoom' verwendet wird)
        glRotatef(tilt,1.0f,0.0f,0.0f);            // kippe die Sicht (indem der Wert aus 'tilt' verwendet wird)

Nun bewegen wir den Stern. Der Stern startet im Mittelpunkt des Screens. Als erstes rotieren wir die Szene auf der Y-Achse. Wenn wir um 90 Grad rotieren, verläuft die X-Achse nicht mehr von links nach recht, sondern in, bzw. raus aus dem Screen. Ein Beispiel um das zu verdeutlichen. Stellen Sie sich vor, Sie stehen im Zentrum eines Raumes. Nun stellen Sie sich vor, dass die an der linken Wand -x steht, and der vorderen Wand steht -z, and der rechte Wand +x und an der hinteren Wand +z. Wenn der Raum sich um 90 Grad drehen würde, Sie sich aber nicht bewegen würden, würde an der vorderen Wand nicht länger -z stehen, sondern -x und +x hinter ihnen. Kapiert? Indem wir die Szene rotieren, ändern wir die Richtung der X und Z Ebenen.

Die zweite Codezeile bewegt zu einem positiven Wert auf der X-Ebene. Normalerweise würde ein positiver Wert auf der X-Ebene uns nach rechts auf dem Screen bewegen (wo +x normalerweise ist), aber da wir auf der Y-Ebene rotiert haben, kann das +X irgendwo sein. Wenn wir um 180 Grad gedreht hätten, würde es auf der linken Seite des Screens, anstatt auf der rechten Seite sein. Wenn wir uns also vorwärts auf der positiven X-Ebene bewegen, könnten wir uns nach links, rechts, vorwärts oder rückwärts bewegen.

        glRotatef(star[loop].angle,0.0f,1.0f,0.0f);    // Rotiere die um den aktuellen Sternen Winkel
        glTranslatef(star[loop].dist,0.0f,0.0f);    // bewege sich vorwärts auf der X-Ebene

Nun so etwas trickreicheren Code. Der Stern ist eigentlich eine flache Textur. Wenn Sie also ein flaches Quadrat im Mittelpunkt des Screens zeichne und es texturieren, würde das gut aussehen. Es würde zu Ihnen gerichtet sein, wie es auch sein sollte. Wenn Sie die Y-Achse aber um 90 Grad drehen, würde die Textur nach links und rechts des Screens zeigen. Alles was Sie sehen würden, wäre eine dünne Linie. Das wollen wir aber nicht. Wir wollen, dass alle Sterne in Richtung Screen zeigen, egal wann und wo, um wieviel wir rotiert oder auch gekippt haben.

Wir machen das, indem wir alle Rotationen rückgängig machen, die wir gemacht haben, kurz bevor wir den Stern zeichnen. Sie machen die Rotation einfach in umgekehrter Reihenfolge wieder rückgängig. So wie wir oben den Screen gekippt haben und dann die Sterne um den aktuellen Winkel gedreht haben. In umgekehrter Reihenfolge un-rotieren (neues Wort) die Sterne um den aktuellen Winkel. Dazu verwenden wir den negativen Wert des Winkels und rotieren um diesen. Wenn wir also um 10 Grad rotiert haben, rotieren wir zurück, indem wir -10 Grad verwenden, damit der Stern zum Screen zeigt. Die erste folgende Zeile macht die Rotation auf der Y-Achse wieder rückgängig. Dann machen wir das Kippen des Screens auf der X-Achse wieder rückgängig. Dazu kippen wir den Screen einfach um -tilt. Nachdem wir die X und Y Rotation wieder rückgängig gemacht haben, zeigt der Stern wieder direkt zum Screen.

        glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);    // drehe um den aktuellen Sternen-Winkel zurück
        glRotatef(-tilt,1.0f,0.0f,0.0f);        // kippe zurück

Wenn twinkle gleich TRUE ist, zeichnen wir einen nicht-rotierenden Stern auf den Screen. Um eine andere Farbe zu erhalten, nehmen wir die maximale Anzahl an Sternen (num) und subtrahieren die aktuellen Sternen-Nummer (loop), dann subtrahieren wir 1, da unsere Schleife nur von 0 bis num-1 läuft. Wenn das Ergebnis gleich 10 wäre, würden wir die Farbe von Stern Nummer 10 verwenden. Auf diesem Weg ist die Farbe der beiden Sterne in der Regel unterschiedlich. Nicht ein guter Weg, aber ein effektiver. Der letzte Wert ist der Alpha-Wert. Je kleiner der Wert, desto dunkler ist der Stern.

Wenn twinkle (glitzern) aktiviert ist, wird jeder Stern zweifach gezeichet. Das wird das Programm ggf. verlangsamen, abhängig von Ihrem Computer. Wenn twinkle aktiviert ist, erzeugt das Mischen der zwei Sterne ein paar wirklich schöne Farben. Da die Sterne nicht rotieren, wird es so aussehen, als wenn die Sterne animiert wären, wenn twinkling aktiviert ist. (schauen Sie selbst, wenn Sie nicht verstehen, was ich meine).

Beachten Sie, wie einfach es ist, Farbe einer Textur hinzuzufügen. Trotz dessen, dass die Textur schwarz-weiß ist, wird Sie jegliche Farbe annehmen, die wir auswählen, bevor wir die Textur zeichnen. Beachten Sie auch, dass wir Bytes für die Farb-Werte verwenden, statt Fließkommazahlen. Selbst der Alpha-Wert ist ein Byte.

        if (twinkle)                    // glitzernde Sterne sind aktiviert
        {
            // gebe ihm eine Farbe, indem Bytes verwendet werden
            glColor4ub(star[(num-loop)-1].r,star[(num-loop)-1].g,star[(num-loop)-1].b,255);
            glBegin(GL_QUADS);            // Fange an, das texturierte Quadrat zu zeichnen
                glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
                glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
                glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
                glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
            glEnd();                // fertig mit dem Zeichnen des texturierten Quadrats
        }

Nun zeichnen wir den Haupt-Stern. Der einzige Unterschied zum obigen Code ist, dass dieser Stern immer gezeichnet wird und das dieser Stern auf der Z-Achse rotiert.

        glRotatef(spin,0.0f,0.0f,1.0f);            // Rotiere den Stern auf der Z-Achse
        // gebe ihm eine Farbe, indem Bytes verwendet werden
        glColor4ub(star[loop].r,star[loop].g,star[loop].b,255);
        glBegin(GL_QUADS);                // Fange an, das texturierte Quadrat zu zeichnen
            glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
            glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
            glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
            glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
        glEnd();                    // fertig mit dem Zeichnen des texturierten Quadrats

Hier erzeugen wir die ganze Bewegung. Wir lassen die normalen Sterne rotieren, indem wir den Wert von spin erhöhen. Dann ändern wir den Winkel jedes Sterns. Der Winkel jeden Sterns wird um loop/num erhöht. Dadurch bewegen sich die Sterne, die weiter Weg vom Mittelpunkt sind, schneller. Die Sterne, die näher am Mittelpunkt sind, rotieren langsamer. Letztendlich verringern wir die Distanz von jedem Stern zum Mittelpunkt des Screens. Das lässt die Sterne so aussehen, als ob Sie im Mittelpunkt des Screen davongesogen werden.

        spin+=0.01f;                    // lässt die Sterne rotieren
        star[loop].angle+=float(loop)/num;        // ändert den Winkel eines Sterns
        star[loop].dist-=0.01f;                // ändert die Distanz eines Sterns

Die folgenden Zeilen überprüfen, ob die Sterne den Mittelpunkt des Screens erreicht haben oder nicht. Wenn ein Stern den Mittelpunkt des Screen erreicht, bekommt er eine neue Farbe und wird 5 Einheiten vom Mittelpunkt weg bewegt, wo er erneut seine Reise zum Mittelpunkt als neuer Stern antreten kann.

        if (star[loop].dist// Ist der Stern bereits im Mittelpunkt
        {
            star[loop].dist+=5.0f;            // bewege den Stern 5 Einheiten vom Mittelpunkt weg
            star[loop].r=rand()%256;        // gebe ihm einen neuen Rot-Wert
            star[loop].g=rand()%256;        // gebe ihm einen neuen Grün-Wert
            star[loop].b=rand()%256;        // gebe ihm einen neuen Blau-Wert
        }
    }
    return TRUE;                        // alles lief glatt
}

Nun fügen wir den Code ein, der überprüft, ob irgendwelche Tasten gedrückt werden. Gehen Sie runter zur WinMain(). Schauen Sie nach der Zeile SwapBuffers(hDC). Wir fügen die Überprüfung für die Tasten direkt hinter dieser Codezeil ein.

Die folgenden Zeilen überprüfen, ob die Taste T gedrückt wurde. Wenn Sie gedrückt wurde und nicht gedrückt bleibt, passiert folgendes: Wenn twinkle gleich FALSE ist, wird die Variable auf TRUE gesetzt. War Sie auf TRUE, wird sie auf FALSE gesetzt. Wenn T gedrückt wird, wird tp gleich TRUE. Das verhindert, dass der Code immer wieder und wieder durchlaufen wird, solange die Taste T gedrückt ist.

        SwapBuffers(hDC);                // Swap Buffers (Double Buffering)
        if (keys['T'] && !tp)                // Wurde T gedrückt und ist tp=FALSE
        {
            tp=TRUE;                // wenn ja, setze tp auf TRUE
            twinkle=!twinkle;            // setze twinkle auf das Gegenteil vom aktuellen Zustand
        }

Der folgende Code überprüft, ob die Taste T losgelassen wurde. Wenn ja, wird tp auf FALSE gesetzt. Das drücken der Taste T macht nichts, solange tp gleich FALSE ist, deshalb ist dieser Codeabschnitt sehr wichtig.

        if (!keys['T'])                    // Wurde die Taste T losgelassen
        {
            tp=FALSE;                // Wenn ja, setze tp auf FALSE
        }

Der Rest des Codes überprüft, ob die Pfeil nach ob, Pfeil nach unten, Seite rauf oder Seite runter Taste gedrückt wurde.

        if (keys[VK_UP])                // Wurde die Pfeil nach oben Taste gedrückt?
        {
            tilt-=0.5f;                // kippe den Screen nach oben
        }

        if (keys[VK_DOWN])                // Wurde die Pfeil nach unten Taste gedrückt?
        {
            tilt+=0.5f;                // kippe den Screen nach unten
        }

        if (keys[VK_PRIOR])                // Wurde die Seite nach oben Taste gedrückt?
        {
            zoom-=0.2f;                // Zoome raus
        }

        if (keys[VK_NEXT])                // Wurde die Seite nach unten Taste gedrückt?
        {
            zoom+=0.2f;                // Zoome rein
        }

Wie in allen vorangegangen Tutorials, stellen wir sicher, dass der Titel des Fensters korrekt ist.

        if (keys[VK_F1])                // Wurde F1 gedrückt?
        {
            keys[VK_F1]=FALSE;            // Wenn ja, setze die Taste auf FALSE
            KillGLWindow();                // Kill unser aktuelles Fenster
            fullscreen=!fullscreen;            // Wechsel zwischen Fullscreen und Fester-Modus
            // Erzeuge unser OpenGL-Fenster neu
            if (!CreateGLWindow("NeHe's Textures, Lighting & Keyboard Tutorial",640,480,16,fullscreen))
            {
                return 0;            // Beenden, wenn das Fenster nicht erzeugt wurde
            }
        }
    }
}

In diesem Tutorial habe ich so detailiert wie möglich versucht zu erklären, wie man ein grauskaliertes Bitmap lädt, das Schwarze drumherum entfernt (mittels Blending), Farbe hinzufügt und das Ganze im 3D Raum bewegt. Ich habe Ihnen ebenso gezeigt, wie man schöne Farbe und Animationen erzeugt, indem man eine zweite Kopie des Bitmaps über das original Bitmap legt. Wenn Sie erstmal ein gutes Verständnis für alles haben, was ich Ihnen bisher beigebracht habe, sollten Sie keine Probleme haben, eigene 3D Demos zu erstellen. Die Grundlagen wurden jetzt alle erklärt!

Jeff Molofee (NeHe)

* DOWNLOAD Visual C++ Code für diese Lektion.

* DOWNLOAD Borland C++ Builder 6 Code für diese Lektion. ( Conversion by Christian Kindahl )
* DOWNLOAD C# Code für diese Lektion. ( Conversion by Brian Holley )
* DOWNLOAD Code Warrior 5.3 Code für diese Lektion. ( Conversion by Scott Lupton )
* DOWNLOAD Cygwin Code für diese Lektion. ( Conversion by Stephan Ferraro )
* DOWNLOAD D Language Code für diese Lektion. ( Conversion by Familia Pineda Garcia )
* DOWNLOAD Delphi Code für diese Lektion. ( Conversion by Michal Tucek )
* DOWNLOAD Dev C++ Code für diese Lektion. ( Conversion by Dan )
* DOWNLOAD Euphoria Code für diese Lektion. ( Conversion by Evan Marshall )
* DOWNLOAD Game GLUT Code für diese Lektion. ( Conversion by Milikas Anastasios )
* DOWNLOAD Irix Code für diese Lektion. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Java Code für diese Lektion. ( Conversion by Jeff Kirby )
* DOWNLOAD Jedi-SDL Code für diese Lektion. ( Conversion by Dominique Louis )
* DOWNLOAD JoGL Code für diese Lektion. ( Conversion by Abdul Bezrati )
* DOWNLOAD LCC Win32 Code für diese Lektion. ( Conversion by Robert Wishlaw )
* DOWNLOAD Linux Code für diese Lektion. ( Conversion by Richard Campbell )
* DOWNLOAD Linux/GLX Code für diese Lektion. ( Conversion by Mihael Vrbanec )
* DOWNLOAD Linux/SDL Code für diese Lektion. ( Conversion by Ti Leggett )
* DOWNLOAD LWJGL Code für diese Lektion. ( Conversion by Mark Bernard )
* DOWNLOAD Mac OS Code für diese Lektion. ( Conversion by Anthony Parker )
* DOWNLOAD Mac OS X/Cocoa Code für diese Lektion. ( Conversion by Bryan Blackburn )
* DOWNLOAD MASM Code für diese Lektion. (Conversion by Nico (Scalp) )
* DOWNLOAD Visual C++ / OpenIL Code für diese Lektion. ( Conversion by Denton Woods )
* DOWNLOAD Power Basic Code für diese Lektion. ( Conversion by Angus Law )
* DOWNLOAD Pelles C Code für diese Lektion. ( Conversion by Pelle Orinius )
* DOWNLOAD Python Code für diese Lektion. ( Conversion by Ryan Showalter )
* DOWNLOAD Solaris Code für diese Lektion. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Visual Basic Code für diese Lektion. ( Conversion by Peter De Tagyos )
* DOWNLOAD Visual Fortran Code für diese Lektion. ( Conversion by Jean-Philippe Perois )
* DOWNLOAD Visual Studio .NET Code für diese Lektion. ( Conversion by Grant James )



Deutsche Übersetzung: Joachim Rohde
Der original Text ist hier zu finden.
Die original OpenGL Tutorials stammen von NeHe's Seite.