Buchempfehlung
Windows-Programmierung. Das Entwicklerhandbuch zur WIN32-API
Windows-Programmierung. Das Entwicklerhandbuch zur WIN32-API
"Der" Petzold, das über 1000 Seiten starke Standardwerk zum Win32-API - besonders nützlich u. a. bei der GUI-Programmierung in FreeBASIC! [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

OpenGL und FreeBASIC - eine kleine Einführung - Teil 4 - Rotieren

von MitgliedEastler_dartSeite 1 von 4

Einleitung

Sie haben doch bestimmt die vorigen drei Tutorialteile gelesen? Wir bauen hier auf das dort Geschriebene auf.

der Boden

Wie im letzten Kapitel schon angedeutet, sieht es viel schöner aus, wenn wir einen Boden unter den Füßen haben. Unsere vor/zurück, hoch/runter und links-rechts Bewegungen drücken sich viel deutlicher aus.

Basteln wir uns also einen Schachbrettboden um zu üben, wie man mit FreeBasic-Befehlen und OpenGL gemeinschaftlich umgeht.

Mittels der Beschreibungsliste Typ GL_QUADS können wir ja Rechtecke in verschiedenen Farben malen. Und Quadrate sind ja auch Rechtecke. Also bauen wir eine SUB, welche per FOR-NEXT-Schleife die Vertex-Listen für Rechtecke erzeugt. Diese SUB nennen wir "Schachbrettboden". Um damit flexibel umgehen zu können, steuern wir über Parameter an die SUB, wie tief und breit der Boden ist, und aus wievielen Quadraten der Boden bestehen soll. Ebenfalls steuern wir über die Paramter, aus welchen zwei Farben die Schachbrettfelder abwechselnd bestehen sollen.

Sie merken schon, das sind ja recht viele Paramter. Wenn das alles in einem Aufruf erfolgen soll, mutiert die aufrufende Befehlszeile zu einer ellenlangen Liste mit Werten. Drum versuche ich mal zu erklären, wie ich sowas über statische Variablen und mehreren SUB-Aufrufen mache. Das hat zwar nicht direkt mit OpenGL zu tun, hilft aber, wenn man unter OpenGL dann Objekte für die Anzeige parat haben will.

Also ran ans Werk, im Anfang unseres Listings unter Declarationen melden wir unsere Sub an:

'-------------------------
'Declarationen
'-------------------------
DECLARE SUB Koordinatensystem(was AS STRING, TxtPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
DECLARE SUB Objekt1()
DECLARE SUB BewegtePunkte()
DECLARE SUB Schachbrettboden(was AS STRING, StrPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
'-------------------------

und am Ende unseres Listings erzeugen wir dann diese SUB:

'-------------------------
SUB Schachbrettboden(was AS STRING, StrPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
END SUB

Um verschiedene Funktionen innerhalb der SUB ausführen zu können, hab ich die STRING-Variable "was" eingearbeitet. Für den eventuellen Fall, daß wir für irgendwelche zukünftigen Funktionen Texte übergeben wollen, ist die Variable StrPara als STRING mit drin. Danach noch drei Parameter vom TYP SINGLE, um Werte zu übergeben.

In dieser Sub entscheiden wir erst mal per BefehlsreferenzeintragSELECT CASE, was der Aufruf eigentlich bewirken soll. Um Schreibfehler mit Groß-/Kleinbuchstaben zu verhindern, wandeln wir dabei den Übergebenen Parameter "was" mit BefehlsreferenzeintragUCASE in Großbuchstaben um.

SELECT CASE UCASE(was)
END SELECT

Als erste Aufrufmöglichkeit sollten wir das Setzen von den entscheidenden Parametern ermöglichen. Diese werden innerhalb der SUB in Variablen gehalten. Damit diese Variablen beim nächsten Aufruf dieser SUB immer noch die Werte enthalten, dimmen wir diese Variablen mit STATIC:

'-------------------------
SUB Schachbrettboden(was AS STRING, StrPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
   STATIC AS SINGLE QuadKantenLaenge, QuadsQuer, QuadsTief
   STATIC AS SINGLE Farbe1Rot, Farbe1Gruen, Farbe1Blau
   STATIC AS SINGLE Farbe2Rot, Farbe2Gruen, Farbe2Blau
   STATIC AS SINGLE StartPosX, StartPosZ, BodenHoehe
   STATIC AS INTEGER ZaehlerX, ZaehlerZ                   :'ForNext-Zählvars, ggf. rekursiver aufruf dieser Sub, drum STATIC
   SELECT CASE UCASE(was)
      CASE "SETZKANTENLAENGE"
         'Aufruf hierfür in Para1 die Länge der Kanten der Quadrate
         QuadKantenLaenge = Para1
      CASE "SETZQUADSZAHL"
         'Aufruf hierfür in Para1 die Anzahl von Quads quer,
         'in Para2 die Anzahl in der Tiefenrichtung
         QuadsQuer = Para1
         QuadsTief = Para2
      CASE "SETZFARBE1"
         'in Para1 Para2 Para2 die Rot Grün und Blauwerte der ersten Quadratfarbe
         Farbe1Rot   = Para1
         Farbe1Gruen = Para2
         Farbe1Blau  = Para3
      CASE "SETZFARBE2"
         'in Para1 Para2 Para2 die Rot Grün und Blauwerte der ersten Quadratfarbe
         Farbe2Rot   = Para1
         Farbe2Gruen = Para2
         Farbe2Blau  = Para3
      CASE "SETZSTARTPOS"
         'in Para1 Para2 Para2 die X und Z Position, von wo begonnen wird,
         'die vielen Quadrate zu erstellen
         StartPosX   = Para1
         StartPosZ   = Para2
         BodenHoehe  = Para3
      CASE "BESCHREIBUNGSLISTEBODEN"
         'Hier erstellen wir die FOR-NEXT-SCHLEIFEN,
         'welche die OpenGL-Beschreibungsliste
         'zum Anzeigen des Bodens erstellen
         glBegin GL_QUADS
            FOR ZaehlerX = 1 TO QuadsQuer     :'Laufnr des grad zu zeichnenden Quads auf der X-Achse
               FOR ZaehlerZ = 1 TO QuadsTief  :'Laufnr des grad zu zeichnenden Quads auf der Z-Achse
                  'Die Farbe festlegen
                  IF ((ZaehlerX+ZaehlerZ)\2)*2=(ZaehlerX+ZaehlerZ) THEN
                     'Wenn die Summe von ZahlerX+ZaehlerY gerade ist Farbe1 nehmen
                     glColor3f Farbe1Rot, Farbe1Gruen, Farbe1Blau
                  ELSE
                     'Wenn die Summe von ZahlerX+ZaehlerY UNgerade ist Farbe2 nehmen
                     glColor3f Farbe2Rot, Farbe2Gruen, Farbe2Blau
                  END IF
                  'Die Eckpunkte der Quadrate benennen wir in der Reihenfolge GEGEN DEN UHRZEIGERSINN, von oben draufschauend
                  glVertex3f StartPosX+(ZaehlerX-1)*QuadKantenLaenge,  BodenHoehe,  StartPosZ+(ZaehlerZ-1)*QuadKantenLaenge
                  glVertex3f StartPosX+ ZaehlerX   *QuadKantenLaenge,  BodenHoehe,  StartPosZ+(ZaehlerZ-1)*QuadKantenLaenge
                  glVertex3f StartPosX+ ZaehlerX   *QuadKantenLaenge,  BodenHoehe,  StartPosZ+ ZaehlerZ   *QuadKantenLaenge
                  glVertex3f StartPosX+(ZaehlerX-1)*QuadKantenLaenge,  BodenHoehe,  StartPosZ+ ZaehlerZ   *QuadKantenLaenge
               NEXT ZaehlerZ
            NEXT ZaehlerX
         glEnd
      CASE ELSE
         'Hier kommen alle SUB-Aufrufe an, welche als
         'was-Parameter einen Eintrag haben, der hier
         'nicht ausgewertet wurde.
         'Tippfehler vom Programmierer????
   END SELECT
END SUB

Damit steht schon mal ein Grundgerüst, mit dem wir in der Lage sind, im Vorfeld, also bevor die Hauptschleife im Hauptprogramm läuft, bereits alle Bedingungen zu setzen, damit innerhalb der zeitkritischen Hauptschleife nur noch der Boden angezeigt werden muß. Also schreiben wir ins Hauptprogramm vor der Hauptschleife die Subaufrufe, mit denen wir den Schachbrettboden initialisieren:

'---------------------------
'HAUPTTEIL
'---------------------------
Schachbrettboden("SetzKantenLaenge", "", 0.5,  0,    0)
Schachbrettboden("SetzQuadsZahl",    "", 24,   24,   0)     :'6 Einheiten +und- = 12Einheiten Koordiantensystem, bei 0.5 Quadgröße 24 Stück
Schachbrettboden("SetzFarbe1",       "", 0,    0,    0.5)   :'erste Farbe dunkleres blau
Schachbrettboden("SetzFarbe2",       "", 0.25, 0.25, 0.25)  :'erste Farbe dunkles grau
Schachbrettboden("SetzStartPos",     "", -6,   -6,   -1)     :'ganz vorne ganz links beginnen, Boden auf Hoehe(3.Para)-1 verlegen(Y)
DO UNTIL Tastendruck = CHR(27)

Im Hauptteil, nach den Tastaturabfragebefehlen und nach dem Aufruf
des Koordinatensystems rufen wir unseren Schachbrettboden zur Anzeige auf:

    glTranslatef XRichtg, YRichtg, ZRichtg    :' Anzeigeposition auf neue Werte einstellen

    glPointSize(5)                             :' Punktgröße auf 5 = deutlich groß
    glColor3f 1.0,0.0,0.0                      :' Anzeigefarbe auf ROT setzen
'    Objekt1()                                  :' Sub Objekt1 aufrufen, in der zwei Punkte an der grad aktuellen Pos erstellt werden
    Koordinatensystem("", "", 0, 0, 0)
    Schachbrettboden("BeschreibungsListeBoden", "", 0, 0, 0):'<-----------------------HIER WIRD UNSER BODEN AUFGERUFEN
    flip                                               :'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an

Wenn Sie das jetzt kompilieren und ausführen, wirds schon ein bißchen eine "richtige" 3D-Welt. Wir haben einen "gefliesten" Fußboden drin.
OpenGl_tut_neuer_Boden
Es ist aber möglich, zuerst mittels STRG/CTRL zusammen mit CursorRunter ein paar Schritte rückwärts zu gehen, bis es nicht mehr weiter geht, dann mittels CursorRunter mit der Kamera immer tiefer zu wandern, bis wir unter dem Fußboden sind.
OpenGL_tut_neuer_Boden_von_unten
Aha, solche farbigen Quads kann man also von beiden Seiten sehen - cool.

eine Pyramide

Nun wollen wir uns auf dem selben Schema wie die Fußboden-Sub eine Routine schreiben, in der Pyramiden erstellt werden. So eine Pyramide ist ja ein einfaches Konstrukt: ein Quadrat als Boden hinlegen, an jeder Kante ein Dreieck dran, und das schräg zur Quadratmitte die Spitze laufen lassen. Die Spitzen der Dreiecke liegen also von oben gesehen genau in der Mitte des Grundquadrates, nur halt höher oben als das Quadrat.

Wir nennen diese SUB "Pyramide" und ermöglichen uns darin die gleichen Variablen wie in der Fußboden-SUB. Mit dieser Declaration sieht der Declarationsbereich dann so aus:

'-------------------------
'Declarationen
'-------------------------
DECLARE SUB Koordinatensystem(was AS STRING, TxtPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
DECLARE SUB Objekt1()
DECLARE SUB BewegtePunkte()
DECLARE SUB Schachbrettboden(was AS STRING, StrPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
DECLARE SUB Pyramide (was AS STRING, StrPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)

Dann am Ende useres Listings schreiben wir die SUB:

'-------------------------
SUB Pyramide(was AS STRING, StrPara AS STRING, Para1 AS SINGLE, Para2 AS SINGLE, Para3 AS SINGLE)
   'Pyramide erstellen, Grundfläche/Quadrat = auf Höhe 0, seitlich mittig auf X- und Z-Achse Positioniert
   'Grundflächengroesse = XLaenge x ZLaenge, Höhe Pyramide = ZLaenge
   STATIC AS SINGLE XLaenge, YLaenge, ZLaenge
   STATIC AS SINGLE Farbe1Rot, Farbe1Gruen, Farbe1Blau
   STATIC AS SINGLE Farbe2Rot, Farbe2Gruen, Farbe2Blau
   STATIC AS SINGLE Farbe3Rot, Farbe3Gruen, Farbe3Blau
   STATIC AS SINGLE Farbe4Rot, Farbe4Gruen, Farbe4Blau
   STATIC AS SINGLE Farbe5Rot, Farbe5Gruen, Farbe5Blau
   STATIC AS INTEGER ZaehlerX, ZaehlerZ                   :'ForNext-Zählvars, ggf. rekursiver aufruf dieser Sub, drum STATIC
   SELECT CASE UCASE(was)
      CASE "SETZLAENGEN"  : XLaenge   = Para1 : YLaenge     = Para2 : ZLaenge     = Para3
      CASE "SETZFARBE1"   : Farbe1Rot = Para1 : Farbe1Gruen = Para2 : Farbe1Blau  = Para3 :'ein Dreieck
      CASE "SETZFARBE2"   : Farbe2Rot = Para1 : Farbe2Gruen = Para2 : Farbe2Blau  = Para3 :'ein Dreieck
      CASE "SETZFARBE3"   : Farbe3Rot = Para1 : Farbe3Gruen = Para2 : Farbe3Blau  = Para3 :'ein Dreieck
      CASE "SETZFARBE4"   : Farbe4Rot = Para1 : Farbe4Gruen = Para2 : Farbe4Blau  = Para3 :'ein Dreieck
      CASE "SETZFARBE5"   : Farbe5Rot = Para1 : Farbe5Gruen = Para2 : Farbe5Blau  = Para3 :'der Boden/Quadrat
      CASE "BESCHREIBUNGSLISTE"
         'die OpenGL-Beschreibungsliste zum Anzeigen der Pyramide erstellen
         glBegin GL_QUADS
            'der Boden der Pyramide als Quadrat, auf Höhe 0(Y-Achse),
            'seitliche Ausrichtungen = Quadratmitte = X-Achsenmitte und Z-Achsenmitte
            'damit Zentriert sitzt, für 1.Punkt einfach halbe Kantenlänge von 0 Abziehen, für 2. dazuaddieren
            'Reihenfolge Eckpunktangabe gegen Uhrzeigersinn VON UNTEN her gesehen (unten=Außenseite später)
            glColor3f  Farbe5Rot        , Farbe5Gruen      , Farbe5Blau
            glVertex3f 0-(XLaenge/2)    , 0  , 0+(ZLaenge/2)
            glVertex3f 0-(XLaenge/2)    , 0  , 0-(ZLaenge/2)
            glVertex3f 0+(XLaenge/2)    , 0  , 0-(ZLaenge/2)
            glVertex3f 0+(XLaenge/2)    , 0  , 0+(ZLaenge/2)
         glEnd
         glBegin GL_TRIANGLES
            '   Dreieckseite 1 =an Kante 1.+2.Quadratpunkt
            glColor3f  Farbe1Rot        , Farbe1Gruen      , Farbe1Blau
            glVertex3f 0-(XLaenge/2)    , 0       , 0-(ZLaenge/2)
            glVertex3f 0-(XLaenge/2)    , 0       , 0+(ZLaenge/2)
            glVertex3f 0                , YLaenge , 0
            '   Dreieckseite 2 =an Kante 2.+3.Quadratpunkt
            glColor3f  Farbe2Rot        , Farbe2Gruen      , Farbe2Blau
            glVertex3f 0+(XLaenge/2)    , 0  , 0-(ZLaenge/2)
            glVertex3f 0-(XLaenge/2)    , 0  , 0-(ZLaenge/2)
            glVertex3f 0                , YLaenge , 0
            '   Dreieckseite 3 =an Kante 3.+4.Quadratpunkt
            glColor3f  Farbe3Rot        , Farbe3Gruen      , Farbe3Blau
            glVertex3f 0+(XLaenge/2)    , 0  , 0+(ZLaenge/2)
            glVertex3f 0+(XLaenge/2)    , 0  , 0-(ZLaenge/2)
            glVertex3f 0                , YLaenge , 0
            '   Dreieckseite 4 =an Kante 3.+1.Quadratpunkt
            glColor3f  Farbe4Rot        , Farbe4Gruen      , Farbe4Blau
            glVertex3f 0-(XLaenge/2)    , 0  , 0+(ZLaenge/2)
            glVertex3f 0+(XLaenge/2)    , 0  , 0+(ZLaenge/2)
            glVertex3f 0                , YLaenge , 0
         glEnd
      CASE ELSE
         'Hier kommen alle SUB-Aufrufe an, welche als
         'was-Parameter einen Eintrag haben, der hier
         'nicht ausgewertet wurde.
         'Tippfehler vom Programmierer????
   END SELECT
END SUB

und im Hauptprogramm vor der Schleife und nach den Init-Befehlen zum Schachbrettboden rufen wir unsere Pyramiden-SUB mit den Initialisierungsparametern auf:

Schachbrettboden("SetzStartPos",     "", -6,   -6,   -1)     :'ganz vorne ganz links beginnen, Boden auf Hoehe(3.Para)-1 verlegen(Y)

Pyramide("SetzLaengen" , "", 1, 1,  1)
Pyramide("SetzFarbe1"  , "", 1, 0, 0)
Pyramide("SetzFarbe2"  , "", 0, 1, 0)
Pyramide("SetzFarbe3"  , "", 0, 0, 1)
Pyramide("SetzFarbe4"  , "", 1, 1, 0)
Pyramide("SetzFarbe5"  , "", 1, 0, 1)

Sodaß wir nur noch in der Schleife die Anzeige der Pyramide mit dem Parameter
"BeschreibungsListe" auslößen müssen:

    Koordinatensystem("", "", 0, 0, 0)
    Schachbrettboden("BeschreibungsListeBoden", "", 0, 0, 0)
    Pyramide("BeschreibungsListe"  , "", 0, 0, 0)        :'<<<<<<<<<<<<HIER PYRAMIDE AUFRUFEN
    flip                                               :'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an

stehende_pyramide.gif
Na, ist sie nicht schön, unsere Pyramide? Aber so starr, unbeweglich? Auf der nächsten Seite bringen wir Bewegung rein.

 

Gehe zu Seite Gehe zu Seite  1  2  3  4  
Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 17.08.2008 von MitgliedEastler_dart angelegt.
  • Die aktuellste Version wurde am 22.07.2012 von MitgliedAffemitwaffel gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen