NeHe - Lektion 05 - 3D Objekte

Lektion 5



Aufbauend auf dem letzten Tutorial, machen wir aus unseren Objekten nun ECHTE 3D Objekte, statt nur 2D Objekte in einer 3D Welt. Wir erreichen das, indem wir links, hinten und rechts dem Dreieck eine Seite hinzufügen und dem Quadrat eine Seite links, rechts, hinten, oben und unten. Dadurch machen wir aus dem Dreieck eine Pyramide und aus dem Qudrat ein Würfel.

Die Farbe der Pyramide lassen wir verlaufen und der Würfel bekommt für jede Seite eine eigene verschiedene Farbe.

int DrawGLScene(GLvoid)                        // Hier kommt der ganze Zeichnen-Kram hin
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // Löscht den Bildschirm und den Depth-Buffer

    glLoadIdentity();                    // Resettet die Ansicht (View)
    glTranslatef(-1.5f,0.0f,-6.0f);                // In den Bildschirm hineinbewegen und dann links

    glRotatef(rtri,0.0f,1.0f,0.0f);                // Rotiere die Pyramide um seine Y-Achse

    glBegin(GL_TRIANGLES);                    // Fange an die Pyramide zu zeichnen

Einige von Ihnen haben den Code aus dem letzten Tutorial genommen und eigene 3D-Objekte gemacht. Eine Sache, die ich ziemlich häufig gefragt wurde, war "wie kommt es, dass meine Objekte sich nicht um die eigene Achse drehen? Es sieht so aus, als ob sie über den ganzen Bildschirm rotieren würden." Damit Ihr Objekt sich um eine Achse drehen kann, muss es UM diese Achse HERUM aufgebaut sein. Sie müssen daran denken, dass das Zentrum eines Objekts 0 auf der X-Achse, 0 auf der Y-Achse und 0 auf der Z-Achse sein sollte.

Der folgende Code erzeugt eine Pyramide um eine zentrale Achse. Die Spitze der Pyramide liegt eine Einheit über dem Zentrum, der Boden der Pyramide liegt eine unter dem Zentrum. Die Spitze liegt genau in der Mitte (null) und die unteren Punkte liegen eine Einheit links und eine rechts vom Zentrum.

Beachten Sie, dass alle Dreiecke in einer gegen den Uhrzeigersinn verlaufenden Rotation gezeichnet werden. Das ist wichtig und wird in einem späterem Tutorial erklärt, aber zum jetzigen Zeitpunkt müssen Sie nur wissen, dass es guter Stil ist, Objekte entweder im Uhrzeigersinn oder gegen den Uhrzeigersinn zu erzeugen, aber Sie sollten nicht beides mischen, es sei denn, Sie haben einen driftigen Grund dafür.

Wir beginnen mit dem Zeichnen der vorderen Seite. Da alle Seiten den obersten Punkt gemeinsam haben, machen wir ihn jeweils Rot für jedes Dreieck. Die Farbe der unteren beiden Punkt des Dreiecks werden andere Farben haben. Die vordere Seite wird einen grünen linken Punkt und einen blauen rechten Punkt haben. Dann wird das Dreieck auf der rechte Seite einen blauen linken Punkt und einen grünen rechten Punkt haben. Dadurch haben wir am Boden jeweils gleichfarbige Eckpunkte.

        glColor3f(1.0f,0.0f,0.0f);            // Rot
        glVertex3f( 0.0f, 1.0f, 0.0f);            // Spitze des Dreiecks (vorne)
        glColor3f(0.0f,1.0f,0.0f);            // Grün
        glVertex3f(-1.0f,-1.0f, 1.0f);            // Linke Seite des Dreiecks (vorne)
        glColor3f(0.0f,0.0f,1.0f);            // Blau
        glVertex3f( 1.0f,-1.0f, 1.0f);            // Rechte Seite des Dreiecks (vorne)

Nun zeichnen wir die rechte Seite. Beachten Sie, dass die beiden unteren Punkte eine Einheit rechts vom Zentrum gezeichnet und die Spitze eine Einheit nach oben auf der Y-Achse und rechts in die Mitte auf der X-Achse gezeichnet wird. Dadurch neigt sich die Seite vom Mittelpunkt von der Spitze auf die rechte Seite des Bildschirms hinunter zum Boden.

Beachten Sie, dass der linke Punkt diesmal blau ist. Dadurch, dass wir ihn blau zeichnen, wird er die selbe Farbe haben, wir die rechte untere Ecke der Vorderseite.

Beachten Sie auch, wie die restlichen drei Seite innerhalb des selben glBegin(GL_TRIANGLES) und glEnd() Paars eingefügt werden, genauso, wie die erste Seite. Da wir das komplette Objekt aus Dreiecken erstellen, weiß OpenGL, dass alle drei Punkte ein Dreieck gezeichnet wird. Wenn die ersten drei Punkte gezeichnet wurden und drei weiter Punkte warten, wird angenommen, dass ein weiteres Dreieck gezeichnet werden soll. Wenn Sie vier statt drei Punkten angeben, würde OpenGL die ersten drei Punkte zeichnen und annehmen, dass der vierte Punkt der Anfang eines neuen Dreiecks ist. Es würde kein Quadrat gezeichnet werden. Stellen Sie also sicher, dass Sie nicht zufällig zuviele Punkte einfügen.

        glColor3f(1.0f,0.0f,0.0f);            // Rot
        glVertex3f( 0.0f, 1.0f, 0.0f);            // Spitze des Dreiecks (rechts)
        glColor3f(0.0f,0.0f,1.0f);            // Blau
        glVertex3f( 1.0f,-1.0f, 1.0f);            // Linke Seite des Dreiecks (rechts)
        glColor3f(0.0f,1.0f,0.0f);            // Grün
        glVertex3f( 1.0f,-1.0f, -1.0f);            // Rechte Seite des Dreiecks (rechts)

Nun für die Rückseite. Erneut Farben wechseln. Der linke Punkt ist nun wieder grün, da die gemeinsame Ecke mit der rechten Seite auch grün ist.

        glColor3f(1.0f,0.0f,0.0f);            // Rot
        glVertex3f( 0.0f, 1.0f, 0.0f);            // Spitze des Dreiecks (hinten)
        glColor3f(0.0f,1.0f,0.0f);            // Grün
        glVertex3f( 1.0f,-1.0f, -1.0f);            // Linke Seite des Dreiecks (hinten)
        glColor3f(0.0f,0.0f,1.0f);            // Blau
        glVertex3f(-1.0f,-1.0f, -1.0f);            // Rechte Seite des Dreiecks (hinten)

Letztendlich zeichnen wir die linke Seite. Die Farben wechseln ein letztes Mal. Der linke Punkt ist blau und verläuft mit dem rechten Punkt der Hinterseite. Der rechte Punkt ist grün und verläuft mit dem linken Punkt der Vorderseite.

Wir sind fertig, mit dem Zeichnen der Pyramide. Da die Pyramide nur um die Y-Achse rotiert, werden wir niemals den Boden sehen, weshalb auch kein Grund besteht, einen zu zeichnen. Wenn Sie etwas herumexperimentieren wollen, versuchen Sie, einen Boden hinzuzufügen, indem Sie ein Quadrat benutzen und rotieren dann um die X-Achse, um zu sehen, ob Sie es auch richtig gemacht haben. Stellen Sie sicher, dass die für die einzelnen Ecken verwendeten Farben des Quadrats mit den Farben der vier Ecken der Pyramide übereinstimmen.

        glColor3f(1.0f,0.0f,0.0f);            // Rot
        glVertex3f( 0.0f, 1.0f, 0.0f);            // Spitze des Dreiecks (links)
        glColor3f(0.0f,0.0f,1.0f);            // Blau
        glVertex3f(-1.0f,-1.0f,-1.0f);            // Linke Seite des Dreiecks (Links)
        glColor3f(0.0f,1.0f,0.0f);            // Grün
        glVertex3f(-1.0f,-1.0f, 1.0f);            // Rechte Seite des Dreiecks (links)
    glEnd();                        // Fertig mit zeichnen der Pyramide

Nun werden wir den Würfel zeichnen. Er besteht aus sechs Quadraten. All diese Quadrate werden gegen den Uhrzeigersinn gezeichnet. Das bedeutet, dass der erste Punkt oben recht, der zweite Punkt oben links, der dritte Punkt unten links und letztendlich der letzte Punk unten rechts gezeichnet wird. Wenn wir die Hinterseit zeichnen, wird es so aussehen, als ob wir mit dem Uhrzeigersinn zeichnen würden, aber Sie müssen im Hinterkopf behalten, dass, wenn wir hinter dem Würfel wären und auf ihn schauen würden, die linke Seite des Bildschirms tatsächlich die rechte Seite des Quadrats ist und die rechte Seite des Bildschirms würde tatsächlich die linke Seite des Quadrats sein.

Beachten Sie, dass wir den Würfel ein klein wenig weiter in den Bildschirm hineinschieben werden, in dieser Lektion. Damit sieht der Würfel etwa genauso groß aus wie die Pyramide. Wenn Sie nur 6 Einheiten in den Bildschirm hineingehen würde, würde der Würfel wesentlich größer aussehen, als die Pyramide und Teile könnten am Rande des Bildschirms abgeschnitten werden. Sie können mit den Einstellungen ein wenig herumspielen und sich anschauen, wir der Würfel kleiner wird, wenn Sie ihn weiter in den Bildschirm verschieben und größer, wenn Sie ihn näher heran holen. Der Grund dafür ist die Perspektive. Objekte sollten in der Entfernung kleiner erscheinen :)

    glLoadIdentity();
    glTranslatef(1.5f,0.0f,-7.0f);                // nach rechts und in den Bildschirm hinein bewegen

    glRotatef(rquad,1.0f,1.0f,1.0f);            // Rotiere den Würfel um X, Y & Z

    glBegin(GL_QUADS);                    // Fange an den Würfel zu zeichnen

Wir werden mit der Oberseite des Würfels anfangen. Wir bewegen uns eine Einheit nach oben, vom Zentrum des Würfels aus gesehen. Beachten Sie, dass die Y-Achse immer gleich eins ist. Dann zeichnen wir das Qudrat auf der Z-Ebenen. Das bedeutet in den Bildschirm hinein. Wir beginnen beim Zeichnen mit dem oberen rechten Punkt der Oberseite des Würfels. Der obere rechte Punkt würde eine Einheit rechts und eine Einheit in den Bildschirm hineingehen. Der zweite Punkt würde eine Einheit nach links und eine Einheit in den Bildschirm hinein sein. Nun müssen wir die Unterkante des Quadrats, zum Betrachter hin, zeichnen. Um das zu machen, bewegen wir uns nicht in den Bildschirm hinein, sondern wir bewegen uns eine Einheit aus dem Bildschirm heraus? Verstanden?

        glColor3f(0.0f,1.0f,0.0f);            // Setze die Farbe auf Grün
        glVertex3f( 1.0f, 1.0f,-1.0f);            // Oben Rechts des Quadrats (oben)
        glVertex3f(-1.0f, 1.0f,-1.0f);            // Oben Links des Quadrats (oben)
        glVertex3f(-1.0f, 1.0f, 1.0f);            // Unten Links des Quadrats (oben)
        glVertex3f( 1.0f, 1.0f, 1.0f);            // Unten Rechts des Quadrats (oben)

Die Unterseite wird exakt genauso gezeichnet wie die Oberseite, da es aber die Unterseite ist, zeichnen wir sie eine Einheit unter dem Zentrum des Würfels. Beachten Sie, das die Y-Achse immer gleich -1 ist. Wenn wir uns unter dem Würfel befinden würden und auf das Quadrat schauen würden, dass den Boden darstellt, würden Sie bemerken, dass die obere rechte Ecke die Ecke ist, die am nähsten zum Betrachter ist, demnach, statt die entfernten Punkte zuerst zu zeichnen, zeichnen wir den dichtesten Punkt zum Betrachter als erstes, dann auf der linken Seite dem Betrachter am nächsten Punkt und gehen dann in den Bildschirm hinein, um die unteren beiden Punkte zu zeichnen.

Wenn Sie sich nicht darüm kümmern, in welcher Reihenfolge die Polygone gezeichnet werden (im Uhrzeigersinn oder eben nicht), könnten Sie auch einfach den selben Code für die Oberseite kopieren und die Y-Achse auf -1 setzen und es würde funktionieren, allerdings würde das ignorieren der Reihenfolge seltsame Resultate mit sich bringen, wenn man später Sachen wie Textur-Mapping einsetzen will.

        glColor3f(1.0f,0.5f,0.0f);            // Setze die Farbe auf Orange
        glVertex3f( 1.0f,-1.0f, 1.0f);            // Oben Rechts des Quadrats (unten)
        glVertex3f(-1.0f,-1.0f, 1.0f);            // Oben Links des Quadrats (unten)
        glVertex3f(-1.0f,-1.0f,-1.0f);            // Unten Links des Quadrats (unten)
        glVertex3f( 1.0f,-1.0f,-1.0f);            // Unten Rechts des Quadrats (unten)

Nun zeichnen wir die Vorderseite. Dazu kommen wir eine Einheit aus dem Bildschirm heraus, vom Zentrum weg, um die Vorderseite zu zeichnen. Beachten Sie, dass die Z-Achse immer gleich null ist. In der Pyramide war die Z-Achse nicht immer eins. An der Spitze war die Z-Achse gleich null. Wenn Sie versucht haben, die Z-Achse im folgenden Code auf null zu setzen, werden Sie bemerkt haben, dass die Ecke, die Sie verändert haben, sich in den Bildschirm neig. Das ist nicht gerade das, was wir nun wollen :)

        glColor3f(1.0f,0.0f,0.0f);            // Setze die Farbe auf Rot
        glVertex3f( 1.0f, 1.0f, 1.0f);            // Oben rechts des Quadrats (vorne)
        glVertex3f(-1.0f, 1.0f, 1.0f);            // Oben links des Quadrats (vorne)
        glVertex3f(-1.0f,-1.0f, 1.0f);            // Unten links des Quadrats (vorne)
        glVertex3f( 1.0f,-1.0f, 1.0f);            // Unten rechts des Quadrats (vorne)

Die hintere Seite ist genauso ein Quadrat wie die vordere Seite, aber sie liegt tiefer im Bildschirm. Beachten Sie, dass die Z-Achse nun -1 für alle Punkte ist.

        glColor3f(1.0f,1.0f,0.0f);            // Setze die Farbe auf gelb
        glVertex3f( 1.0f,-1.0f,-1.0f);            // Unten links des Quadrats (hinten)
        glVertex3f(-1.0f,-1.0f,-1.0f);            // Unten rechts des Quadrats (hinten)
        glVertex3f(-1.0f, 1.0f,-1.0f);            // Oben rechts des Quadrats (hinten)
        glVertex3f( 1.0f, 1.0f,-1.0f);            // Oben links des Quadrats (hinten)

Nun müssen wir nur noch zwei weitere Qudrate zeichnen und wir sind fertig. Wie immer, werden Sie bemerken, dass eine Achse für alle Punkte immer gleich ist. In diesem Fall ist die X-Achse immer -1. Das ist so, weil wir immer links vom Zentrum zeichnen, weil es die linke Seite (des Würfels) ist.

        glColor3f(0.0f,0.0f,1.0f);            // Setze die Farbe auf Blau
        glVertex3f(-1.0f, 1.0f, 1.0f);            // Oben Rechts des Quadrats (Links)
        glVertex3f(-1.0f, 1.0f,-1.0f);            // Oben Links des Quadrats (Links)
        glVertex3f(-1.0f,-1.0f,-1.0f);            // Unten links des Quadrats (Links)
        glVertex3f(-1.0f,-1.0f, 1.0f);            // Unten Rechts des Quadrats (Links)

Das ist die letzte Seite um den Würfel fertig zu stellen. Die x-Achse ist jeweils gleich 1. Gezeichnet wird gegen den Uhrzeigersinn. Wenn Sie wollen, können Sie diese Seite weglassen und eine Kiste draus machen :)

Oder wenn Sie etwas herumexperimentieren wollen, können Sie jeweils versuchen die Farben für jeden Eckpunkt des Würfels zu verändern, um einen Farbverlauf wie bei der Pyramide zu erzeugen. Sie können ein Beispiel dafür sehen, indem Sie Evil's erstes GL demo von meiner Seite herunterladen. Starten Sie es und drücken Sie TAB. Sie werden einen schön gefärbten Würfel sehen mit einem schönen Farbverlauf auf allen Seiten.

        glColor3f(1.0f,0.0f,1.0f);            // Setze die Farbe auf violett
        glVertex3f( 1.0f, 1.0f,-1.0f);            // Oben Rechts des Quadrats (Rechts)
        glVertex3f( 1.0f, 1.0f, 1.0f);            // Oben Links des Quadrats (Right)
        glVertex3f( 1.0f,-1.0f, 1.0f);            // Unten Links des Quadrats (Right)
        glVertex3f( 1.0f,-1.0f,-1.0f);            // Unten rechts des Quadrats (Rechts)
    glEnd();                        // Fertig mit dem Zeichnen von Quadraten

    rtri+=0.2f;                        // Inkrementiere die Rotations-Variable für das Dreieck
    rquad-=0.15f;                        // Dekrementiere die Roatations-Variable für das Quadrat 
    return TRUE;                        // Weiter geht's
}

Am Ende dieses Tutorials sollten Sie ein besseres Verständnis haben, wie Objekte im 3D-Raum erzeugt werden. Sie müssen sich den OpenGL Screen als ein gigantisches Stück Graphen-Papier vorstellen, mit vielen durchsichtigen Schichten dahinter. Fast wie ein gigantischer Würfel, der aus Punkten besteht. Einige dieser Punkte verlaufen von links nach recht, einige von oben nach unten und einige von vorne nach hinten, innerhalb des Würfels. Wenn Sie sich die Tiefe in den Bildschirm hinein vorstellen können, sollten Sie keine Probleme habe, neue 3D Objekte zu erstellen.

Wenn Sie Probleme beim Verstehen des 3D-Raumes haben, seien Sie nicht frustriert. Es kann am Anfang sehr schwierig sein. Ein Objekt wie der Würfel ist ein gutes Beispiel, von dem man lernen kann. Wenn Sie es bemerkt haben, wird die hintere Seite genau gleich gezeichnet wie die vordere Seite, nur einfach tiefer in den Bildschirm hinein. Spielen Sie mit dem Code ein wenig herum und wenn Sie es nicht verstehen, schicken Sie mir eine E-Mail und ich versuchen Ihnen Ihre Fragen zu beantworten.

Jeff Molofee (NeHe)

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

* DOWNLOAD ASM Code für diese Lektion. ( Conversion by Foolman )
* DOWNLOAD Borland C++ Builder 6 Code für diese Lektion. ( Conversion by Christian Kindahl )
* DOWNLOAD C# Code für diese Lektion. ( Conversion by Sabine Felsinger )
* DOWNLOAD VB.Net CsGL Code für diese Lektion. ( Conversion by X )
* 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 GLUT Code für diese Lektion. ( Conversion by Andy Restad )
* DOWNLOAD Irix Code für diese Lektion. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Java Code für diese Lektion. ( Conversion by Jeff Kirby )
* DOWNLOAD Java/SWT Code für diese Lektion. ( Conversion by Victor Gonzalez )
* DOWNLOAD Jedi-SDL Code für diese Lektion. ( Conversion by Dominique Louis )
* DOWNLOAD JoGL Code für diese Lektion. ( Conversion by Kevin J. Duling )
* 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 Power Basic Code für diese Lektion. ( Conversion by Angus Law )
* DOWNLOAD Pelles C Code für diese Lektion. ( Conversion by Pelle Orinius )
* DOWNLOAD Perl Code für diese Lektion. ( Conversion by Cora Hussey )
* DOWNLOAD Python Code für diese Lektion. ( Conversion by Tony Colston )
* DOWNLOAD REALbasic Code für diese Lektion. ( Conversion by Thomas J. Cunningham )
* DOWNLOAD Scheme Code für diese Lektion. ( Conversion by Jon DuBois )
* DOWNLOAD Solaris Code für diese Lektion. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Visual Basic Code für diese Lektion. ( Conversion by Ross Dawson )
* 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.