Buchempfehlung
Visual Basic 6 Kochbuch
Visual Basic 6 Kochbuch
Viele praktische Tipps zum Programmieren mit Visual Basic 6, die sich oft auch auf FB übertragen lassen. [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 3 - Bewegen

von MitgliedEastler_dartSeite 1 von 3

Einleitung

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

Was ist unser Ziel?
Im letzten Kapitel hatten wir alle Primitiven besprochen und auch ein Koordinatensystem entworfen und anzeigen lassen. Jedoch, solange wir unsere 3D-Welt nur von einer festen Position aus anschauen, wirkt das Koordinatensystem nicht grad hilfreich.

Also haben wir uns als Ziel gesetzt, beim Betrachten unserer 3D-Welt durch eben diese wandern zu können. Dabei auch aus allen möglichen Positionen unsere Objekte zu betrachten wäre sehr aufschlussreich.

Bevor wir mit diesem "Wandern" loslegen, müssen noch ein paar grundsätzliche Sachen besprochen werden.

der Fotograf

Ihnen ist sicherlich aufgefallen, dass ich bei den Beispielen immer für die Z-Achse einen Minuswert angegeben habe, und dort nicht auch mit dem Wert Null gearbeitet habe.
Dieses Mysterium will ich hier aufklären, dazu muss ich aber etwas ausholen.

Was machen wir hier eigentlich?
Wir zermartern uns die Köpfe, um unsere Objekte mit echten 3D-Werten zu erzeugen, damit im Ramspeicher der Grafikkarte dann alles so drin steht, wie es eben im richtigen Leben/im wirklichen 3D ist.
Das ganze nimmt sich dann OpenGL und errechnet daraus, wo auf dem 2D-Monitor ein Pixel in welcher Farbe zu setzen ist, damit das Auge so getäuscht wird, dass es das Ganze als 3D ans Gehirn meldet.
Das kommt uns doch irgendwie bekannt vor? Richtig.
Beim Fotografieren läuft es fast genauso. Da wird ein 3D-Objekt so auf 2D-Papier gebannt, dass die Augen des Betrachters denken, das wäre 3D.

gluPerspective

Und mit diesem Vergleich wollen wir hier auch arbeiten. OpenGL geht im Grunde genauso vor, wie eine Kamera. Im "OpenGL Init Bereich" initialisieren wir ja OpenGL auf eine Grundeinstellung, mit der sich hier erst mal arbeiten lässt.
Da drin steht unter Anderem der Befehl:
gluPerspective 45.0, 800.0/600.0, 0.1, 100.0
In diesem Befehl steht die 45.0 für die gleiche Sache, wie an einer Kamera die Objektivweite. Aber werden Sie jetzt nicht euphorisch, ich hab schon mal ausprobiert, dort einen Wert von 100 rein zu setzten. Ist ne ganz schön breite Sichtweite, die dabei rauskommt, aber ein ebener Boden wird dabei "aufgewölbt".
Die 45-Grad-Sichtweise ist ein ausprobierter Wert, bei dem alles, was OpenGL anzuzeigen hat, recht realistisch aussieht.
Kennen Sie diese "Fischaugenbilder" aus der Fotografie? In denen alles so aussieht, als würde man durch ein Waschmaschinentürglas gucken?
So was ähnliches passiert auch OpenGL, wenn diese 45 Grad noch weiter aufgespannt werden.
Die 800/600-Angabe in dem Befehl sagt openGL, in welchem Verhältnis, die Breite und Länge des Ausgabebereichs auf dem Monitor stehen.
Beim TV kennt man so was durch den Begriff 16:9.
Beachten Sie dabei, dass 800/600 eine Rechenformel ist, OpenGL kriegt hier über den Prozessor den ausgerechneten Wert von 1.33333 übergeben, von den geschriebenen Zahlen 800 und 600 sieht OpenGL nichts.
Die letzten beiden Parameter "0.1" und 100.0" sagen openGL:
Alles, was von der (fiktiven) Kamera zwischen 0.1 und 100.0 Maßeinheiten entfernt ist, wird angezeigt, was weiter davor (Abstand < 0.1) oder weiter dahinter (Abstand > 100) liegt, bitte nicht anzeigen.
Ja warum denn nicht alles anzeigen? Das hängt erstens davon ab, ob das sinnvoll ist. Solange Sie mit Objekten umgehen, welche nur einige Maßeinheiten groß sind, verbleibt bei einer Entfernung von 100 Einheiten eh höchstens ein einziges Pixel. Aber OpenGL rechnet ne Ewigkeit an diesem einen Pixel rum, damit die Farbe des Pixels dem entspricht, was in Realität bei so einem Verhältnis von Größe und Entfernung zu sehen wäre.
Sollten Sie mal Ihr Superprogramm optimieren wollen, hier ist so ein Ansatzpunkt. Wenn Ihre Objekte tatsächlich so weit verstreut sind, und Sie diesen Wert "100" minimieren, kann OpenGL bestimmt schneller werden, jedoch mit dem Hintergrund, dass weit weg liegende Objekte nicht berechnet, und damit aber auch nicht angezeigt werden.

Sie sehen, wie beim Fotografieren. Wenn es weit weg ist, nimmt man dort auch ganz andere Objektive, weil es mit dem normalen nur noch kleine Punkte zu sehen gibt.

der Standpunkt

Ein anderer Aspekt ist, die Beweglichkeit der Kamera.
Wenn Sie im Garten eine schöne Blume fotografieren wollen, achten Sie ja darauf, dass die Kamera diese Blume so einfängt, dass auf dem fertigen Bild die Blume in der schönsten Sichtweise zu sehen ist.
Sie nehmen also die Kamera, tragen sie zum Objekt, drehen und kippen diese, gehen näher hin oder weiter weg, bis Sie dann, wenn alles stimmt, auf den Auslöser drücken.

Genau das gibt es bei OpenGL auch. Auch hier wird auf dem Monitor nur das angezeigt, was die (virtuelle) Kamera im Moment grad sieht. Und aus diesem Grund hatte ich in den bisherigen Beispielen alles zur X-Achse innerhalb der Einheiten -3 bis +3 angesetzt und die Objekte in der Tiefe / Z-Achse auf Pos -6 gesetzt.
Der Berg kam da zum Propheten. Um Sie nicht vorab mit diesen Theorien über Kameras und aufgenommene Bilder zu überhäufen, hatte ich Sie nicht die Kamera justieren lassen, sondern die Objekte dahin gesetzt, wo die Kamera grad hinguckt.

Also, in OpenGL lässt sich die "Kamera" ebenfalls auf andere Positionen setzen, drehen oder kippen. Um darüber zu reden, möchte ich erst mal die Ausgangsposition beschreiben.

Mit unserem Grundprogramm, bei dem wir einiges an Einstellungen vordefiniert haben, sagen wir OpenGL nichts darüber, wo die Kamera steht.
Kurzerhand bleibt sie da, wo OpenGL die ursprünglich hinsetzt, nämlich auf der Position 0/0/0 (Leere Variablen). Als Drehrichtung ist für die Kamera ebenfalls der Winkelgrad "0" (leere Variable) eingestellt, und dass heißt, sie "schaut" vom Nullpunkt aus entlang der negativen Z-Achse.

Ja, das ist auch so eine Fehlerquelle, wenn man neu mit OpenGL Versuche anstellt. Wenn Sie im Garten stehen, die Blume vor sich haben und nach links statt zur Blume hin knipsen, ist diese Blumen halt nicht auf dem Bild, oder?

Für die Grundstellung bezüglich Kamera ergibt sich folgendes Bild:
OpenGL_Tut_Kamera_sieht_polygon
Bei diesem Bild hab ich "unser" Koordinatensystem verwendet, das Polygon aus dem Beispiel bzw. Dreieck_FAN anzeigen lassen, eine symbolische Kamera (von hinten gesehen) eingesetzt und das Ganze aus einer "Weltall"-Perspektive festgehalten.

Auf dieser Skizze sieht man das bisher in der Theorie Besprochene ganz deutlich. Die Kamera sitzt auf 0/0/0, sieht in den negativen Bereich (schwarze Einteilungsstriche=negativ) der Z-Achse (Blaue = 3.Farbe in RGB = 3.Achse = Z-Achse).
Die Beispiele wurden immer auf Z-Achsenpunkt -6 angezeigt, das ergibt einen "schönen" Abstand von 6 Einheiten zur Kamera, damit sind die Beispielobjekte immer "voll auf dem Bild".

den Standpunkt verschieben

So, nachdem ich nun annehmen kann, dass Sie auch verstehen, wovon ich hier schreibe, legen wir mal los mit dem Verschieben.
Der Befehl, für Änderungen an Positionen lautet:
glTranslate
Da wir hier dem Befehl Floating-Point-Parameter angeben wollen, hängen wir noch ein "f" hintendran:
glTranslatef
Als Parameter gibt man 3 Werte an, die in Reihenfolge für X- dann Y- dann Z-Achse gelten.
glTranslatef 1.0, 2.0, 3.0
Würde alles, was danach kommt, um eine Einheit positiv auf der X-Achse verschieben, zusätzlich 2 Einheiten auf der Y-Achse und auch 3 Einheiten auf der Z-Achse.

Soviel wollen wir nun nicht gleich ausprobieren.
Wir probieren mal im folgenden Beispiel das Verschieben zweier Punkte.
Dabei lernen wir gleich noch einen neuen Befehl:
glPointSize
Mit diesem Befehl ändern wir die Größe der nachfolgend anzuzeigenden Punkte. Damit wir unsere beiden Beispielpunkte auch ganz deutlich sehen, ändern wir die Größe mit glPointSize(3) auf 3.
Als Beispielpunkte nehmen wir einen auf glVertex3f 1, 1, 0 und einen auf glVertex3f -1, -1, 0.
Hier wieder Beispielprogrammzeilen, die wir in der SUB Objekt1 eintragen, und die aus bisherigen Beispielen bereits drin stehenden löschen wir.
Danach sieht die SUB Objekt1() folgendermaßen aus:

'-------------------------
SUB Objekt1()
  glPointSize(3)           'Größe der anzuzeigenden Punkte = 3
  glTranslatef 0, 0, -6.0  'Verschieben um 6 Einheiten negativ auf der Z-Achse (3.Para=Z)
  glBegin GL_POINTS        'Beschreibungsliste für Punkte beginnen
     glVertex3f   1,  1, 0 'einen Punkt auf 1/1/0
     glVertex3f  -1, -1, 0 'noch einen Punkt, dieser auf -1/-1/0
  glEnd                    'Ende der Beschreibungsliste (hier für Punkte)
END SUB
'-------------------------

Ändern Sie unser Beispielprogramm so ab, dass in Objekt() die Zeilen, wie hier gezeigt, drin stehen. Um unsere Anzeige klar und eindeutig zu gestalten, Kommentieren wir in der Hauptschleife den Aufruf für unser Koordinatensystem aus:

'   Koordinatensystem("", "", 0, 0, 0)

sodass wirklich nur die beiden Beispielpunkte anzuzeigen sind:

Wenn Sie nun unser Beispielprogramm kompilieren und ausführen, werden Sie wohl 2 mal hinschauen um dann zu fragen, was für einen Stuss erzählt der denn, das geht ja gar net! Denn so sieht die Ausgabe aus:
OpenGL_Tut_zwei_punkte_verschoben
Ja, ist klar, ein weiteres kompliziertes Verhalten von OpenGL ist zusätzlich noch zu klären:
Das Verschieben der beiden Punkte um 6 Einheiten nach hinten (auf Z -6) hat einwandfrei geklappt, nur halt nicht nur einmal, viele Male, ganz viele Male sogar.
Wie jetzt? steht doch nur einmal drin?

nicht Foto sondern Video

Das ist das Grundprinzip von OpenGL. Ich hatte es ganz am Anfang schon mal angedeutet. OpenGL läuft in einer Schleife, immer wieder diese Schleife, bis wir diese mit Esc abbrechen.
Und nur durch den zwingenden Aufbau, die OpenGL-Befehle in einer Schleife ablaufen zu lassen, ist es möglich, auch bewegte Bilder mit OpenGL zu erzeugen.

Als Erstes müssen wir unsere Denkweise mit dem Fotografieren anpassen. Denn OpenGL läuft nicht wie ein Foto, sondern wie eine Videokamera.
Es wird immer wieder und immer wieder aus den 3D-Daten ein Bild erzeugt und dieses am Monitor angezeigt. Nur halt, solange wir nur feste Objekte erstellen, kriegen wir das nicht mit. Es errechnet sich ja immer wieder das gleiche Bild, sieht dann aus wie ein Foto.

Wenn wir unsere Hauptschleife genau ansehen, können wir das daraus erlesen. Es wird / werden eine/mehrere Subs aufgerufen, welche Beschreibungslisten für Objekte enthalten, danach kommt: flip.
Und genau, flip heißt, hallo OpenGL, das waren alle Beschreibungen, schieß ein Foto von unserer 3D-Welt und schick es auf den Monitor. FreeBasic findet dann "LOOP" und beginnt die Schleife von neuem.

Und genau da beginnt unser Beispiel mit den 2 Punkten andere Wege zu gehen, als wir das erwartet haben.
Wenn die Schleife das erste Mal durchlaufen wird, kommt genau das raus, was wir erwartet haben, aber Sekundenbruchteile später läuft die Schleife ein zweites Mal durch und OpenGL werden wieder 2 Punkte beschrieben.
Aber: OpenGL hat noch die verschobene
Position (0,0,-6) voll drauf, kriegt diesen Befehl ein zweites Mal, und verschiebt zusätzlich ein zweites Mal um weitere -6 Einheiten auf der Z-Achse. Im dritten Durchlauf der Schleife noch mal und noch mal und noch mal.
Und die ganz schlauen Füchse unter euch müssten gleich rufen, und warum sehen wir dann ganz viele Punkte auf dem Bild, und nicht nur zwei ganz weit hinten?
Richtig. Ein zweites Problem ist noch mit drin.
Genau so, wie OpenGL von der verschobenen Position im zweiten Durchlauf noch weiß, kennt es auch noch die Punkte aus dem ersten Durchlauf.
Und?.......Richtig, zu den zwei bestehenden aus dem ersten Durchlauf, setzt OpenGL noch mal 2 Punkte dazu, nur halt -6 weiter hinten.
Und im Dritten? Ja, wieder 2 Punkte dazu, und wieder weitere 6 Einheiten weiter hinten.

Das hat für uns Programmierer schon Vorteile, dass OpenGL so arbeitet, aber in unseren Beispielen ist das hinderlich, denn wir müssen dagegen an gehen.

3D-Welt löschen

Zuerst eliminieren wir den Fehler, dass es mit jedem Programmschleifendurchlauf immer mehr Punkte werden - wir löschen am Schleifenbeginn einfach alles, was in unserer 3D-Welt vorhanden ist.
Mit dem OpenGL-Befehl glClear können Sachen gelöscht werden, als Parameter wird angegeben was zu löschen ist. In unserem Fall den Buffer für Farbe und Tiefe (dort stehen die errechneten 3D-Objekte drin).
Unsere Befehlszeile sieht dann so aus:
glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
und das fügen wir in der Hauptschleife gleich nach der Tastaturabfrage mit INKEY-Befehl ein:

DO UNTIL Tastendruck = CHR(27) :'die Schleife solange immer wiederholen, bis in der Variablen Tastendruck die Esc-Taste (chr(27) steht
   '---------------------------
   'ProgrammSchleife
   '---------------------------
   Tastendruck = INKEY   'Jeder Tastendruck wird sofort in die Variable Tastendruck gespeichert

   glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT  :'<<<<<<<<<<<<<<<<<<<<<<das fügen wir ein

   Objekt1               'die sub mit unseren Beispielbeschreibungslisten durchlaufen
   flip                  'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an
   '---------------------------
   'Ende der Schleife
   '---------------------------
LOOP
END

Wenn Sie nun wiederum das ganze kompilieren und das fertige Programm starten, könnten Sie mit blitzschnellen Augen 2 weiße Punkte sehen, die zur Monitormitte zusammenlaufen und dann ganz verschwinden?. Das kommt auch auf Ihre Hardware an. Ich arbeite auf einer 5200Mhz (2x2600) CPU mit Onboardgrafik.
Damit kann ich die Punkte kurz sehen. Kann durchaus sein, wenn Sie eine ordentliche separate Grafikkarte haben, dass Sie aufgrund des viel schnelleren OpenGL-Ablaufs leer ausgehen.

Aber wir sehen damit, ein Problem ist weg. Es sind jetzt nicht mehr "immer mehr Punkte", sondern nur noch zwei. Aber diese werden durch glTranslate in der Sub bei jedem Schleifendurchlauf immer noch jedes Mal 6 Einheiten noch weiter hinter verschoben, bis diese dann auf einer Entfernung von über 100 Einheiten weg sind, was unsere Videokamera dann nicht mehr sieht (in den Einstellungen OpenGL Init, im Befehl gluPerspective hatten wir ja festgelegt, dass alles, was über 100 Einheiten weg ist, nicht mehr darzustellen ist.

ein Stapel / STACK

Um dieses Phänomen des addierten Verschiebens weg zu kriegen, müssen wir uns über Stacks unterhalten. Denn irgendwie möchten wir ja OpenGL erklären, dass der VerschiebeBefehl glTranslate in der SUB immer von einem festen Punkt aus zu erfolgen hat, egal, wie oft diese Sub durch die Schleife aufgerufen wird.
Am Besten, OpenGL vor dem glTranslate-Befehl auf eine feste, immer gleiche Position setzen, und dann erst verschieben.
Und das geht über STACKS - Stapel.

Erst mal ein "lebendiges" Beispiel für einen Stack:
Nehmen wir mal an, Sie haben 3 verschiedene Aufgaben sowieso schon zu erledigen,
Rasen mähen
Fenster putzen
Auto waschen
Sie wissen aber, das wird nicht alles sein, während Sie diese Aufgaben durchführen.
Es kommen Leute, und geben Ihnen noch neue Aufgaben dazu. Also führen Sie einen STACK ein.
Sie schreiben für jede Aufgabe einen Zettel und legen diese drei Zettel aufeinander = sie "pushen" die Zettel auf den Stapel.
Dann lesen Sie den obersten Zettel = Autowaschen und legen los.
Dann sind sie grad am Autowaschen, kommt einer und bittet Sie, einkaufen zu gehen.
Sie schreiben also "Einkaufen" auf einen Zettel, legen diesen auf den Stapel wieder
ganz oben drauf und düsen los in den Einkaufsmarkt.
Nachdem Sie dann zurück sind, alles eingekauft haben, ist die Aufgabe ja erledigt.
Also zum Stapel/Stack, den obersten Zettel mit "Einkaufen" wegschmeißen.
Was lesen Sie jetzt? Autowaschen? aha, Sie waren wohl noch nicht fertig? also weiter damit.
Irgendwann ist das Auto ja sauber=Aufgabe erledigt, also oberster Zettel mit Autowaschen wegschmeißen, was lesen Sie "Fenster Putzen". Mann, Sie sind
aber vielbeschäftigt. - grins
Jedenfalls, sobald jemand kommt, was Neues will, Zettel schreiben, obendrauf, das ist Ihre Aufgabe. In ihrer "Programmierung" steht dann, sobald eine Aufgabe fertig ist, Zettel vom Stack runter-popen und weg damit. Das was drunter vor kommt, ist Ihre nächste Aufgabe.
Jetzt müssen Sie nur noch darauf achten, dass es nicht mehr Zettel werden, als in Ihrer Ablagebox Platz dafür ist, und auch, dass Sie nicht Zettel wegschmeißen wollen, obwohl gar keine mehr drin sind.
Das in etwa wäre so ein STACK im richtigen Leben.

Genau solche Stacks verwendet auch OpenGL, für einige Dinge, für jede Sache einen eigenen, separaten Stack. Und - Sie vermuten es schon - es gibt auch einen solchen Stack für die Position, von der alle Befehle ausgehen.
Jeder Befehl, der sich in unserer 3D-Welt positionieren muss, schaut auf den obersten Zettel auf dem "Positionsstack", und errechnet von der darauf stehenden Position aus weiter. Nach dem Erststart von OpenGL steht auf diesem obersten Zettel - wer hätte das gedacht - die Position 0,0,0.
Das geht erst mal einfach und gut, unsere Beispiele in den vorigen Kapiteln liefen ja alle.
Aber nun kommt glTranslate ins Spiel. Der ließt die Position auf dem obersten Zettel, zählt zu jeder der 3 Richtungen (X/Y/Z) die in den Parametern des Befehls stehenden Weiten dazu, radiert den Zettel leer, und schreibt die neue errechnete Position wieder drauf.
Jetzt können Sie es sich ja denken, wenn unsere Hauptschleife ein zweites und weiteres Mal durchlaufen wird, ließt glTranslate wieder die (abgeänderte) Position des obersten Blattes aus, zählt seine Parameter noch mal dazu, radiert den Zettel wieder leer und schreibt die wiederum neue Position drauf.
Alle Befehle, die sich in der 3D-Welt positionieren müssen, richten sich dann entsprechen nach den neuen Werten.

Aha, und nun? - wir schieben glTranslate einfach zusätzliche Zettel unter, dann wird auf dem zusätzlichen Zettel radiert und retuschiert, wir schicken unsere Kommandos los, die sich nach den verschobenen Werten richten sollen und schmeißen den Zettel danach einfach weg.
Darunter kommt ja der "alte" Zettel mit der ursprünglichen Position wieder drunter vor, alles was nach unserer Schieberei kommt, richtet sich dann wieder nach der vorherigen, alten Position.

Ein Beispiel:
Wir haben eine SUB, in welcher eine Beschreibungsliste für ein Haus drin steht. Sinnigerweise sind die Koordinaten für die Teile des Hauses so gewählt, dass die linke, untere, vordere Ecke des Hauses auf 0,0,0 liegt.
Wir wollen dieses Haus aber auf der Position 2,2,2 in unserer kleinen OpenGL-3D-Welt einfügen.

Also schummeln wir erst einen zweiten Zettel mit der gleichen aktuellen Position, wie schon oben drauf steht auf den PositionsSTACK.
Mit glPushMatrix wird ein zusätzlicher Zettel mit der aktuellen Position auf den Stapel gelegt. Wir merken uns, jetzt liegt die aktuelle Position zweimal auf dem Stapel.
Danach verschieben wir alle kommenden Anzeigen mit glTranslate 2,2,2 um 2 Einheiten in jede der 3 Richtungen, was bedeutet, auf dem obersten der zwei Zettel mit der aktuellen Pos wird die neu errechnete Position eingetragen.
Jetzt rufen wir die SUB ErstelleHausEins auf. In der Sub wird zwar ab 0,0,0 gebaut, aber das relativ zu der Pos auf dem Stack, und somit an Stelle 2/2/2.
Das Haus ist fertig, jetzt müssen wir die alte Position wieder herstellen.
Mit glPopMatrix wird der oberste Zettel von den beiden auf dem Stapel weggeschmissen, was liegt drunter? die Position, wie sie war, bevor wir den Verschiebebefehl gesendet hatten.
Mit dieser Technik bauen wir ein Haus, verschoben zur eigentlichen Position, und danach ist alles wie es vor dem Hausbau war, nur das Haus steht eben dort, wo wir es haben wollen.

zwei Häuser

Jetzt könnten Sie sogar das ganze mit anderen Verschiebewerten noch mal exerzieren, dann haben Sie 2 Häuser mit ein und der selben SUB,
Sie merken: Eine SUB, mehrere (gleiche) Häuser, durch den Verschiebe-Befehl.

So, mit diesem Wissen wollen wir nun an unsere zwei Punkte rangehen.
In unserer Objekt()-SUB schreiben wir nur die Beschreibungsliste der beiden Punkte:

'-------------------------
SUB Objekt1()
  glBegin GL_POINTS        'Beschreibungsliste für Punkte beginnen
     glVertex3f   1,  1, 0 'einen Punkt auf 1/1/0
     glVertex3f  -1, -1, 0 'noch einen Punkt, dieser auf -1/-1/0
  glEnd                    'Ende der Beschreibungsliste (hier für Punkte)
END SUB
'-------------------------

und setzen das Ändern der Punktgröße, Farbeinstellung und die Verschiebung auf Pos 0/0/-6 in der Hauptschleife VOR dem Sub-Objekt1()Aufruf.
Und dieses ganze Konstrukt Beginnen wir mit Push der Matrix (Positionsstapel) und beenden mit Pop der Matrix.

'-------------------------
DO UNTIL Tastendruck = CHR(27)                         :'die Schleife solange immer wiederholen, bis in der Variablen Tastendruck die Esc-Taste (chr(27) steht
   Tastendruck = INKEY                                 :'Jeder Tastendruck wird sofort in die Variable Tastendruck gespeichert
   glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT  :'bisherig erstellte Objekte löschen, unsere 3D-Welt wieder von Neuem an erstellen
   glPushMatrix                                        :'aktuelle Position sichern (2.Zettel mit gleicher Pos auf PositionsSTACK)
   '---------------------------
   'ProgrammHauptSchleife
   '---------------------------
'   Koordinatensystem("", "", 0, 0, 0)                 :' Das Koordinatensystem passt noch nicht, ALS KOMMENTAR AUSREMMEN ODER GANZ RAUSLÖSCHEN

    glPointSize(3)                                     :'Größe der anzuzeigenden Punkte = 3 schon hier setzen
    glColor3f 1.0, 1.0, 1.0                            :'Anzeigefarbe auf weiß setzen
    glTranslatef 0, 0, -6.0                            :'Verschieben um 6 Einheiten negativ auf der Z-Achse (3.Para=Z)
    Objekt1                                            :'Aufruf unserer Sub mit den zwei Punkten

    glPointSize(10)                                    :'Größe der anzuzeigenden Punkte = 3 schon hier setzen
    glColor3f 1.0, 1.0, 0.0                            :'Anzeigefarbe auf GELB setzen
    glTranslatef 0, 0, -6.0                            :'Verschieben um 6 Einheiten negativ auf der Z-Achse (3.Para=Z)
    Objekt1                                            :'Aufruf unserer Sub mit den zwei Punkten

    flip                                               :'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an
   '---------------------------
   'Ende der HauptSchleife
   '---------------------------
   glPopMatrix                                         :' Aufgabe erledigt, den zweiten Zettel mit der geänderten Pos wegschmeißen, dann ist Alte Pos wieder aktuelle Pos
LOOP
'-------------------------

Dieses Listing kompiliert und ausgeführt ergibt folgende Anzeige:
OpenGL_Tut_zwei_weisse_und_gelbe_punkte
Noch mal, was passiert hier:
Wir starten in der Hauptschleife mit leerer 3D-Welt (glClear) und erstellen eine Kopie (zweiter Zettel) der Aktuellen Position auf dem STACK (glPushMatrix).
Wir setzen die Punktgröße auf 3 und die Anzeigefarbe auf weiß, die Anzeigeposition verschieben wir UM 6 Einheiten nach hinten.
Dann rufen wir unsere SUB auf, welche einfach nach aktuellen Einstellungen 2 Punkte anzeigt.
Wenn dann diese beiden (weißen, in Größe 3, um -6 auf der Z-Achse verschobenen) Punkte erstellt sind, ändern wir die Punktgröße auf 10, setzen die Anzeigefarbe auf Gelb und verschieben NOCHMAL um 6 Einheiten nach hinten (Z). Nun rufen wir die selbe Punkt-SUB noch einmal auf, diese setzt wieder 2 Punkte nach aktuellen Einstellungen, und das sind jetzt gelbe, größere Punkte, noch weiter weg von der Kamera.
Danach "restaurieren" wir mit PopMatrix die ursprüngliche Anzeigeposition wieder, damit die Anzahl an Zetteln auf dem MatrixSTACK wieder stimmt und für eventuelle noch kommende weitere Objekterstellungen wieder von der ursprünglichen Position ausgegangen wird.

Was wissen wir jetzt?
Mit glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT müssen wir für jeden Schleifendurchlauf die bereits erstellten Objekte wieder löschen.
Mit glPushMatrix müssen wir vor jedem Verschiebebefehl (glTranslate) die aktuelle Anzeigeposition sichern, und hinterher mit glPopMatrix wieder auf den unveränderten Punkt restaurieren, um nach einem Verschiebebefehl den zuvorigen Zustand wieder hergestellt zu haben.

Was denken wir dabei?
Wie in dem Beispiel oben gezeigt, können wir jetzt SUBs schreiben, welche nur die eigentlichen Objekte anzeigen, per Push/Pop und Translate ist es dann ein Einfaches, ein und das selbe Objekt (SUB) mehrfach an verschiedenen Positionen erstellen zu lassen.

 

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

  Versionen Versionen