Tutorial
OpenGL und FreeBASIC - eine kleine Einführung - Teil 4 - Rotieren
von Eastler_dart | Seite 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 SELECT CASE, was der Aufruf eigentlich bewirken soll. Um Schreibfehler mit Groß-/Kleinbuchstaben zu verhindern, wandeln wir dabei den Übergebenen Parameter "was" mit UCASE 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.
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.
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
Na, ist sie nicht schön, unsere Pyramide? Aber so starr, unbeweglich? Auf der nächsten Seite bringen wir Bewegung rein.
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|
|