www.codeworx.org/opengl-tutorials/Tutorial 5: 3D-Objekte

Lektion 5 "3D Objekte"

- Download des Arbeitsbereiches

In dieser Lektion wird die letzte so erweitert werden, das "echte" 3D-Objekte entstehen und nicht nur einfache Grundformen die sich irgendwie drehen. Dazu wird das Dreieck zur Pyramide, das Quadrat zum Würfel und auch das 8-Eck bekommt mehrere Seiten dazu.

Neue Variablen müssen nicht deklariert werden, also wird gleich DwawGlScene bearbeitet.

int DrawGLScene(GLvoid) 
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
  // Die vorherige Szene wird vom Bildschirm gelöscht, 
  // damit die neuen nicht einfach über die alten    
  // Objekte gezeichnet werden

  glLoadIdentity(); 
  // modelview-Matrix wird zurückgesetzt  

  glTranslatef(-1.5f,-1.5f,-8.0f);
  // Auf der X-Achse 1.5 Einheiten zurück (Nach links)
  // Auf der Y-Achse 1.5 Einheiten zurück (Nach unten)
  // Auf der Z-Achse 6 Einheiten zurück (In den Bildschirm hinnein.)

Da die 3D-Objekte etwas mehr Platz beanspruchen wird die obere Änderung nltig. (Die Pyramide wird damit ein Stück nach unten geschoben, damit sie nicht den Würfel verdeckt.)

Bei den Formen ist es wichtig, daß sich die Drehachse genau im Mittelpunkt befinet. Wird also eine Form gezeichnet und vorher eine Drehachse eingestellt so müssen alle Punkte dieses Objektes um einen Punkt 0,0,0 angelegt werden. Dazu ein Beispiel:

Es wird eine Drehachse mit glRotatef() angelegt, danach ein Quadrat gezeichnet mit den Koordinaten:

(0,0,0) für die untere linke Ecke
(1,0,0) für die untere rechte Ecke
(1,1,0) für die obere rechte Ecke
(0,1,0) für die obere linke Ecke

Die Kantenlänge beträgt also 1. Beim Ausführen wird man sehr schnell feststellen müssen, das sich das Quadrat nur um eine seiner Kanten dreht und nicht um seinen Mittelpunkt. Das Problem läßt sich recht einfach lösen indem die Koordinaten um einen Mittelpunkt (0,0,0) herrum angeornet werden. nämlich:

(-0.5, -0.5, 0) für die untere linke Ecke
(0.5, -0.5, 0) für die untere rechte Ecke
(0.5, 0.5, 0) für die obere rechte Ecke.
(-0.5, 0.5, 0) für die obere linke Ecke

Das gleiche gilt natürlich auch für 3-dimensionale Objekte.

Zuerst wird aber die Pyramide gezeichnet. Die Vorderseite kommt als allererstes, die unteren Ecken dieses Dreiecks müssen auf der Z-Achse ein Stück zurückgesetzt werden. Außerdem folgen alle Koordinaten der Seitenflächen zwischen einem glBegin(GL_TRIANGLES); und einem glEnd();. OpenGL packt also bei GL_TRIANGLES immer drei hintereinnanderstehende Koordinaten zu einem Dreieck zusammen. Alle Dreiecke haben die gemeinsame Koordinate (0.0f, 1,0f, 0,0f) die genau auf der Y-Achse liegt, um die die Pyramide ja insgesamt gedreh werden soll.

  glRotatef(rdreieck,0.0f,1.0f,0.0f);
  // Die Pyramide soll um die Y-Achse rotiert werden
glBegin(GL_TRIANGLES);
// Es folgen die Koordinaten für mehrere Dreiecke glColor3f(0.0f,0.0f,1.0f); // das vordere soll blau werden glVertex3f( 0.0f, 1.0f, 0.0f); // oben (vorderes Dreieck) glVertex3f(-1.0f,-1.0f, 1.0f); // links (vorderes Dreieck) glVertex3f( 1.0f,-1.0f, 1.0f); // rechts (vorderes Dreieck)
glColor3f(1.0f,0.0f,0.0f); // das rechte soll rot werden
glVertex3f( 0.0f, 1.0f, 0.0f); // oben (rechtes Dreieck) glVertex3f( 1.0f,-1.0f, 1.0f); // links (rechtes Dreieck) glVertex3f( 1.0f,-1.0f, -1.0f); // rechts (rechtes Dreieck)
    glColor3f(0.0f,1.0f,0.0f); // das hintere grün
    glVertex3f( 0.0f, 1.0f, 0.0f);  // oben (hinteres Dreieck)
    glVertex3f( 1.0f,-1.0f, -1.0f); // links (hinteres Dreieck)
    glVertex3f(-1.0f,-1.0f, -1.0f); // rechts (hinteres Dreieck)
 
    glColor3f(1.0f,1.0f,0.0f); // und das linke gelb 
glVertex3f( 0.0f, 1.0f, 0.0f); // oben (linkes Dreieck) glVertex3f(-1.0f,-1.0f,-1.0f); // links (linkes Dreieck) glVertex3f(-1.0f,-1.0f, 1.0f); // rechts (linkes Dreieck)
  glEnd(); // Zeichenaktion beenden

  glLoadIdentity(); // zurücksetzen

glLoadIdentity() muss malwieder aufgerufen werden, damit sich die vorherige Rotation nicht mehr auf die nächsten Objekte auswirkt. Es wird also nicht nur der Zeichner, sondern auch die Rotation zurückgesetzt.

glTranslatef(-0.5f,0.8f,-9.0f);
// 5 Einheiten nach links, 0.8 Einheiten nach unten, // 9 Einheiten "in" den Schirm
glRotatef(rviereck,1.0f,1.0f,0.0f); // Der Würfel soll um die X- und Y-Achse rotiert werden
glBegin(GL_QUADS); // Vierecke zeichnen

Und jetzt zu dem Würfel, bestehend aus 6 Quadraten (QUADS). Es wird mit der oberen Fläche des Würfels angefangen. Die Y-Koordinate muss immer 1.0f bleiben. Zuerst wird der obere rechten Punkt der oberen Fläche des Würfels gezeichnet.
  glColor3f(0.0f,1.0f,0.0f); // Mit Blau gehts los
glVertex3f( 1.0f, 1.0f,-1.0f); // oben rechts (OBEN) glVertex3f(-1.0f, 1.0f,-1.0f); // oben links (OBEN) glVertex3f(-1.0f, 1.0f, 1.0f); // unten links (OBEN) glVertex3f( 1.0f, 1.0f, 1.0f); // unten rechts (OBEN)

Die untere Fläche des Würfels wird genauso gezeichnet, allerdings eine Einheit unterhalb des Zentrums. Der Y-Wert ist immer -1.

   glColor3f(1.0f,0.5f,0.0f); // Orange
glVertex3f( 1.0f,-1.0f, 1.0f); // oben rechts (UNTEN) glVertex3f(-1.0f,-1.0f, 1.0f); // oben links (UNTEN) glVertex3f(-1.0f,-1.0f,-1.0f); // unten links (UNTEN) glVertex3f( 1.0f,-1.0f,-1.0f); // unten rechts (UNTEN)

Jetzt wird die vordere Seite des Würfels gezeichnet. Die Z-Achse ist immer 1.

   glColor3f(1.0f,0.0f,0.0f); // Rot
   glVertex3f( 1.0f, 1.0f, 1.0f); // oben rechts (VORNE)
   glVertex3f(-1.0f, 1.0f, 1.0f); // oben links (VORNE)
   glVertex3f(-1.0f,-1.0f, 1.0f); // unten links (VORNE)
   glVertex3f( 1.0f,-1.0f, 1.0f); // unten rechts  (VORNE)

Die hintere Fläche wird genauso dargestellt wie die vordere, aber weiter in den Bildschirm hinein versetzt. Daher wird nur die Z-Koordinate verändert.

   glColor3f(1.0f,1.0f,0.0f); // Gelb
   glVertex3f( 1.0f,-1.0f,-1.0f); // oben rechts (HINTEN)
   glVertex3f(-1.0f,-1.0f,-1.0f); // oben links (HINTEN)
   glVertex3f(-1.0f, 1.0f,-1.0f); // unten links (HINTEN)
   glVertex3f( 1.0f, 1.0f,-1.0f); // unten rechts  (HINTEN)

Jetzt noch 2 weitere Flächen, die linke zuerst. (Und wie immer bleibt eine Seite unverändert.)

   glColor3f(0.5f,0.5f,0.5f); // Grau
   glVertex3f(-1.0f, 1.0f, 1.0f); // oben rechts (LINKS)
   glVertex3f(-1.0f, 1.0f,-1.0f); // oben links (LINKS)
   glVertex3f(-1.0f,-1.0f,-1.0f); // unten links (LINKS)
   glVertex3f(-1.0f,-1.0f, 1.0f); // unten rechts  (LINKS)

Nun noch die letzte Seite des Würfels. Diese kann auch weggelassen werden um eine Kiste zu zeichnen ;)

   glColor3f(1.0f,0.0f,1.0f); // Violet
   glVertex3f( 1.0f, 1.0f,-1.0f); // oben rechts (RECHTS)
   glVertex3f( 1.0f, 1.0f, 1.0f); // oben links (RECHTS)
   glVertex3f( 1.0f,-1.0f, 1.0f); // unten links (RECHTS)
   glVertex3f( 1.0f,-1.0f,-1.0f); // unten rechts (RECHTS)

glEnd(); // Zeichenaktion beenden glLoadIdentity(); // zurücksetzen

glTranslatef(3.0f,0.0f,-9.0f);
// 3 Einheiten nach rechts, 9 Einheiten "in" den Schirm

glRotatef(rachteck,0.0f,0.0f,1.0f); // Die Firgur soll um die Z-Achse rotiert werden

Jetzt soll das Achteck 3-dimensional gezeichnet werden. Dazu werden an vier Seiten des schon bestehenden Achtecks, Dreiecke angezeichnet, diese haben dann jeweils zwei gemeinsame Koordinaten mit der Grundform, dem Achteck. Alle vier Dreiecke haben eine gemeinsame Koordinate (den Mittelpunkt). Zur besseren Vorstellung am besten das Programm ausführen. Das Ergebnis sieht etwas nach einem zu vier Seiten geöffneten, achteckigen Zelt aus.
  glBegin(GL_POLYGON); // Ein Polygon (in diesem Falle ein Achteck.)
// jede Ecke bekommt eine andere Farb glColor3f(1.0f,0.0f,0.0f); // rot glVertex3f(-0.5f, 1.5f, -1.0f); // obere Ecke links glVertex3f( 0.5f, 1.5f, -1.0f); // obere Ecke recht
glColor3f(0.0f,0.0f,1.0f); // blau glVertex3f( 1.5f, 0.5f, -1.0f); // rechte Ecke oben glVertex3f( 1.5f,-0.5f, -1.0f); // rechte Ecke unten glColor3f(0.0f,1.0f,0.0f); // grün glVertex3f( 0.5f,-1.5f, -1.0f); // untere Ecke rechts glVertex3f(-0.5f,-1.5f, -1.0f); // untere Ecke links glColor3f(1.0f,1.0f,0.0f); // gelb glVertex3f(-1.5f,-0.5f, -1.0f); // linke Ecke unten glVertex3f(-1.5f, 0.5f, -1.0f); // linke Ecke oben glEnd(); // Zeichenaktion beenden
  glBegin(GL_TRIANGLES); //Dreiecke sollen gezeichnet werden
  // jedes bekommt eine andere Farbe
    glColor3f(1.0f,0.0f,0.0f); // rot
    glVertex3f( 0.0f, 0.0f, 1.0f); // gemeinsamer Mittelpunkt
    glVertex3f(-0.5f, 1.5f, -1.0f); // obere Ecke links
    glVertex3f( 0.5f, 1.5f, -1.0f); // obere Ecke rechts
    glColor3f(0.0f,0.0f,1.0f); // blau
    glVertex3f( 0.0f, 0.0f, 1.0f); // gemeinsamer Mittelpunkt
    glVertex3f( 1.5f, 0.5f, -1.0f); // rechte Ecke oben
    glVertex3f( 1.5f,-0.5f, -1.0f); // rechte Ecke unten
    glColor3f(0.0f,1.0f,0.0f); // grün
    glVertex3f( 0.0f, 0.0f, 1.0f); // gemeinsamer Mittelpunkt
    glVertex3f( 0.5f,-1.5f, -1.0f); // untere Ecke rechts
    glVertex3f(-0.5f,-1.5f, -1.0f); // untere Ecke links
    glColor3f(1.0f,1.0f,0.0f); // gelb
    glVertex3f( 0.0f, 0.0f, 1.0f); // gemeinsamer Mittelpunkt
    glVertex3f(-1.5f,-0.5f, -1.0f); // linke Ecke unten
    glVertex3f(-1.5f, 0.5f, -1.0f); // linke Ecke oben
  glEnd(); // Zeichenaktion beenden
Und auch die Drehwinkel müssen wieder bei jedem Durchgang geändert werden.
  rdreieck -= 0.4f; 
  // Der Drehwinkel des Dreiecks soll bei 
  // jedem Durchgang um 0,4f verringert werden.

rviereck += 0.7f; // Der Drehwinkel des Vierecks soll bei // jedem Durchgang um 0,7f erhöht werden.
rachteck += 0.56f;
// Der Drehwinkel des Achtecks soll bei // jedem Durchgang um 0,56f erhöht werden werden.
return TRUE; // Alles hat geklappt }

Last but not least, die Namensänderung

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow)
{
  (...) gekürzt

   if (!CreateGLWindow("Opengl Tutorial 4 - 3D Objekte - 
                        www.codeworx.org",640,480,16,fullscreen))
     {
       return 0; // Falls ein Fehler auftrat, beenden
     }

  (...)
 

Auch ein Arbeitsbereich ist wieder verfügbar. Weiter zur nächsten Lektion.