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 3 - Bewegen

von MitgliedEastler_dartSeite 2 von 3

es bewegt sich doch

ABER: eigentlich wollten wir ja die Kamera verschieben, um unser Koordinatensystem besser anschauen zu können?. Dazu müssen wir das grad Erlernte noch in "Bewegung" umsetzen, und das gehen wir jetzt mal durch.

Erinnern sie sich an das (noch) falsche Beispiel mit den beiden Punkten, die nach dem Löschen der bis dahin erstellten Objekte zu zwei Punkten mutierten, die zur Bildschirmmitte wanderten und dann ganz verschwunden sind?
Das mein ich jetzt, dieses "Wandern".

Das ist eigentlich nix Schwieriges, es geht nur darum per glTranslate die Verschiebekoordinaten so zu setzen, dass mit jedem erstellten Videobild (Schleifendurchlauf) das Objekt um einen kleinen Wert versetzt angezeigt wird, das menschliche Auge nimmt solche kleinen Veränderungen als "Bewegung" wahr, eben wieder mal wie beim Videos drehen.

Und diese "kleinen" Verschiebungen realisieren wir nicht über Push-Pop oder ähnliches, sondern schlichtweg mit FreeBasic-Variablen auf folgender Grundlage:
Wir sind nun soweit, ein Objekt beliebig zu positionieren. Tragen wir jedoch einen festen Verschiebewert in den glTranslate-Befehl ein, ist es wie ein Stilleben. Es wird mit jedem Hauptschleifendurchlauf zwar ein neues Bild erstellt, aber unser Objekt bleibt auf immer der gleichen Position "stehen".
An den Push/Pop und glClear-Befehlen wollen wir nicht "rumschrauben", so wie wir diese jetzt haben, ist gut damit zu leben.
Eleganter geht das, indem wir den Verschiebebefehl nicht mit festen Werten sondern mit FreeBasic-Variablen "füttern", und die Werte in diesen übergebenen Variablen ändern wir passend zur gewünschten Bewegung in jedem Schleifendurchlauf.
Also: Variablen Dimmen, in jedem Schleifendurchlauf den Wert in den Variablen ändern, und den Verschiebe-Befehl (glTranslate) mit dieser/diesen Variablen füttern.
Klingt doch einfach, oder?
Dazu folgendes Beispiel:
wir erstellen eine neue SUB, die wir BewegtePunkte() nennen. Also im Declare-Teil folgender zusätzlicher Eintrag:

'-------------------------
'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()                            :'<<<<<<<<<<<<<< die hier neu dazu
'-------------------------

Im Hauptteil rufen wir nun eben diese neue SUB BewegtePunkte auf,
die bisherige Objekte1() wird aus der neuen Sub angesprochen,
also löschen wir deren Aufruf in der Hauptschleife:

'-------------------------
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
   '---------------------------

    glColor3f 1.0,1.0,0.0                              :' Anzeigefarbe auf GELB setzen
    glPointSize(5)                                     :' Punktgröße auf 5 = deutlich groß
    BewegtePunkte()                                    :' <<<<<<<<<<<<<<<<<<<<<<<<Hier wird unsere neue Sub aufgerufen

    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
'-------------------------

Unsere bisherige SUB Objekte1() sieht ja immer noch so aus:

'-------------------------
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
'-------------------------

die lassen wir einfach so, und als neue SUB BewegtePunkte() schreiben wir:

'-------------------------
SUB BewegtePunkte()
   STATIC AS SINGLE Seite, Hoehe, Tiefe  :'Static, damit die Vars beim nächsten Aufruf der Schleife immer noch den Wert haben
   Seite=Seite + 0.01                    :'Die Variable Seite um 0.01 erhöhen, somit bei jedem Bild Objekt um 0.01 Einheiten weiter rechts anzeigen
   IF Seite > 2 THEN Seite = -2          :'damit halten wir den Wert von Seite zwischen -3 und +3
   glTranslatef Seite, 0, -6             :'wir Positionieren die Anzeige fest auf -6 der Z-Achse = im Kamerabereich und beweglich auf der X-Achse
   Objekt1()
END SUB
'-------------------------

Hierzu möchte ich anmerken, dass ich die Variablen für die Verschiebungspositionen nicht mit DIM sondern mit STATIC dimme, weil damit FreeBasic den Inhalt dieser Variablen immer noch kennt, wenn die Sub ein zweites/drittes... Mal aufgerufen wird. Als SINGLE müssen die Variablen gedimmt werden, weil wir mit z.b.0.01-Werten arbeiten, also brauchen wir einen Variabelentyp, welche auch Kommastellen sich merken kann. Und da SINGLE eine FloatingPoint - Kommazahl-Variable ist, hängen wir dem Befehl glTranslate ein f an, damit glTranslate die Parameter als Kommazahlvariable auswertet.

Wenn Sie das Beispiel kompilieren und starten, sehen Sie zwei gelbe Punkte, die von links beginnend, nach rechts wandern, um dann wieder links zu beginnen, nach rechts zu wandern, bis Sie die Escape-Taste für Programmende drücken.
Hier ein Bild davon:
2_bewegte_punkte.gif
Sollten bei Ihnen hardwarebedingt die Punkt nur gaaaaanz laaaaangsam wandern, dann ändern Sie in der SUB BewegtePunkte() die Zeile Seite=Seite + 0.01 in Seite=Seite + 0.1, damit geht's 10x schneller.

Wenn wir jetzt so zufrieden wären, wär's ja einfach ;-)

es bewegt sich zwei mal

Wie sieht's denn aus, wenn wir die SUB BewegtePunkte ein zweites Mal versetzt aufrufen?
Also in die Hauptschleife auf folgenden Stand bringen:

   'ProgrammSchleife
   '---------------------------
'   Koordinatensystem("", "", 0, 0, 0)  :' Das Koordinatensystem passt noch nicht, ALS KOMMENTAR AUSREMMEN ODER GANZ RAUSLÖSCHEN

    glColor3f 1.0,1.0,0.0               :' Anzeigefarbe auf GELB setzen
    glPointSize(5)                      :' Punktgröße auf 5 = deutlich groß
    BewegtePunkte()                     :' <<<<<<<<<<<<<<<<<<<<<<<<Hier wird unsere neue Sub aufgerufen
    glColor3f 1.0,0.0,0.0               :' Anzeigefarbe auf ROT setzen
    glTranslatef 1, -0.5, 0             :'wir Positionieren die Anzeige fest auf -6 der Z-Achse = im Kamerabereich und beweglich auf der X-Achse
    BewegtePunkte()                     :' <<<<<<<<<<<<<<<<<<<<<<<<Hier wird unsere neue Sub aufgerufen

    flip                                :'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an
   '---------------------------
   'Ende der Schleife

4_bewegte_punkte_falsch.gif
Es werden vier Punkte, zwei gelbe aus dem ersten Aufruf von BewegtePunkte() und zwei rote Punkte aus dem zweiten Aufruf angezeigt.
Aber genau hingeguckt, die roten Punkte sollten eigentlich zueinander den selben Abstand haben, wie die Gelben zueinander.
Irgendwas läuft da wieder quer?
Ja richtig. Da wir glTranslatef 2 mal aufrufen (1 x im Hauptprogramm und noch mal in der Sub "BewegtePunkte()", erhalten wir wieder "addierte" Verschiebewerte beim zweiten Aufruf.
Also unser Push und Pop der Matrix in der Hauptschleife hält nur soweit, dass nach Schleifenende wieder von unserer eingestellten Position aus angezeigt wird. Sobald innerhalb eines einzelnen Schleifendurchlaufes mehrere Verschiebungen aufgerufen werden, werden diese wieder addiert.

Also müssten wir für den Ersten und den Zweiten Aufruf jeweils zuvor Pushen und danach per Pop restaurieren, um auch für den zweiten Aufruf von der selben Startposition auszugehen:

   'ProgrammSchleife
   '---------------------------
'   Koordinatensystem("", "", 0, 0, 0)  :' Das Koordinatensystem passt noch nicht, ALS KOMMENTAR AUSREMMEN ODER GANZ RAUSLÖSCHEN

    glPushMatrix    :'<<<<<<<<<<<<<<<<<<  für akt. StartPosition einen zweiten Zettel Pushen
    glColor3f 1.0,1.0,0.0               :' Anzeigefarbe auf GELB setzen
    glPointSize(5)                      :' Punktgröße auf 5 = deutlich groß
    BewegtePunkte()                     :' Hier wird unsere Sub aufgerufen
    glPopMatrix     :'<<<<<<<<<<<<<<<<<<  zweiten Zettel vom STACK löschen (urspr. Pos kommt wieder drunter vor)
    glPushMatrix    :'<<<<<<<<<<<<<<<<<<  wieder zweiter Zettel mit urspr. Position auf den STACK Pushen
    glColor3f 1.0,0.0,0.0               :' Anzeigefarbe auf ROT setzen
    glTranslatef 1, -0.5, 0             :'wir Positionieren die Anzeige fest auf -6 der Z-Achse = im Kamerabereich und beweglich auf der X-Achse
    BewegtePunkte()                     :'Hier wird unsere Sub aufgerufen
    glPopMatrix     :'<<<<<<<<<<<<<<<<<<  zweiten Zettel vom STACK löschen (urspr. Pos kommt wieder drunter vor)

    flip                                :'liebes OpenGL, zeig alles, was in der Schleife für dich vornedran steht, auf Monitor an
   '---------------------------
   'Ende der Schleife

4_bewegte_punkte_richtig.gif
So, jetzt passt es. die Roten Punkte sind wie die Gelben, nur um 1 Einheit in positiver Richtung zur X-Achse versetzt (nach rechts), und eine halbe Einheit in negativer Y-Richtung (nach unten).

Sie haben sich das Ganze doch richtig verdeutlicht? In der Hauptschleife wird vor dem Sub-Aufruf ein Verschiebebefehl gesetzt (von wo aus die bewegte Anzeige starten soll), in der BewegtePunkte-Sub wird dazu zusätzlich noch mal um die Bewegung versetzt. Kein Pop dazwischen, also werden in der BewegtePunkte-Sub die Verschiebelängen zu den Angaben vor dem SubAufruf in der Hauptschleife addiert (der oberste Zettel ausradiert und die addierte Pos draufgeschrieben).
Nach dem ersten Aufruf, die ersten beiden Punkte, kommt ein Pop.
Was steht dann auf dem obersten Zettel? Richtig, die verschobene Position aus dem Aufruf der Hauptschleife (push ist ja gleich am Beginn der SUB).
Also, beim zweiten mal zwei (rote) Punkte anzeigen, wird wieder von der verschobenen Pos aus der Hauptschleife ausgegangen und von da aus mit dem Translate in der SUB verschoben.
Nach diesem zweiten Anzeigen der (roten) Punkte kommt wieder ein Pop, oberster Zettel weg, was steht auf dem drunter? Die verschobene Pos aus der Hauptschleife. Damit verhält sich diese SUB bezüglich der Anzeigeposition neutral, mit der Pos, mit der die Sub aufgerufen wird, beendet die Sub sich auch.

 

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