Räuber-Beute-Simulation

Transcrição

Räuber-Beute-Simulation
Simulation und Visualisierung des
Räuber-Beute-Algorithmus
Hausarbeit zum Fach Systemprogrammierung der Hochschule Fulda
WS 2006 / 2007
von
Dirk Fidorski
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Inhaltsverzeichnis
1. Das Räuber-Beute-Modell................................................................................................................3
1.1 Überblick – Modell-Theorie................................................................................................. 3
1.2 Geschichtlicher Hintergrund................................................................................................. 3
1.3 Die Erweiterbarkeit des Modells...........................................................................................4
2. Das Programm – Anwenderinformationen.......................................................................................4
2.1 Inhalt des Datenträgers..........................................................................................................4
2.2 Systemvoraussetzungen und Installation.............................................................................. 5
2.3 Funktionsumfang und Bedienung......................................................................................... 5
3. Die Programmentwicklung...............................................................................................................7
3.1 Überblick – die verwendeten Techniken.............................................................................. 7
3.2 Programmierung des Räuber-Beute Algorithmus.................................................................7
3.2.1 Anforderungen an das Programm.............................................................................7
3.2.2 Die Klassenstruktur.................................................................................................. 8
3.3 Die Grafische Benutzeroberfläche...................................................................................... 10
3.3.1 Programmierung des Haupfensters.........................................................................10
3.3.2 Ausgabe der Wachstumsfunktionen....................................................................... 12
3.3.3 Ausgabe der Population in 2D................................................................................12
3.4 Java3D / Ausgabe der Population in 3D............................................................................. 12
3.4.1 Aufbau der 3D-Ausgabe – Der Konstruktor...........................................................12
3.4.2 Die Teilgraphen...................................................................................................... 13
3.4.3 Die Simulation........................................................................................................ 14
3.4.4 Die Kamera – Optionen zur Laufzeit......................................................................14
4. Die Modelle / 3D-Modellierung mit Maya.................................................................................... 14
4.1 Die Modellierungssoftware.................................................................................................14
4.2 Die Modelle.........................................................................................................................15
4.2.1 Die Beute – Der Roadrunner.................................................................................. 16
4.2.2 Der Räuber – Wile E. Coyote................................................................................. 18
4.3 Exportieren der Modelle..................................................................................................... 20
5. Der Object-Loader..........................................................................................................................20
5.1 Funktionsweise....................................................................................................................20
5.2 Aufgetretene Probleme....................................................................................................... 20
6. Aufwandsdarstellung...................................................................................................................... 21
6.1 Programmteil Java...............................................................................................................21
6.2 Programmteil Java3D..........................................................................................................21
6.3 Programmteil Maya.............................................................................................................21
7. Quellen........................................................................................................................................... 22
8. Anhang........................................................................................................................................... 23
Räuber-Beute-Simulation
-2-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
1. Das Räuber-Beute-Modell
1.1 Überblick – Modell-Theorie
In einem begrenzten Gebiet leben zwei Populationen, wobei sich eine der Populationen
(die Räuber) von der anderen ernährt (Beute). Die maximale Größe der Population wird
durch die Platzkapazität des gegebenen Gebiets begrenzt. Die Räuber sind auf genügend
Nahrung, also Beute, angewiesen, weshalb das Aussterben der Räuber unmittelbar aus
dem Aussterben der Beute resultiert. Die Größen der Populationen beeinflussen sich
gegenseitig. Je mehr Beute existiert, umso einfacher fällt es den Räubern Nahrung zu
finden, umgekehrt erhöht sich die Überlebenschance eines Beutetieres und damit die
Wachstumsrate der Beutepopulation je weniger Räuber vorhanden sind.
Bei günstigen Ausgangswerten der beiden Populationen ergibt sich ein
Gleichgewichtszustand, welcher beide Populationen vor dem Aussterben bewahrt. Dieses
Gleichgewicht spiegelt sich in versetzten periodischen Schwankungen der
Wachstumsfunktionen der beiden Populationen wider.1
1.2 Geschichtlicher Hintergrund
Das mathematische Modell, welches zur Berechnung der Räuber-Beute-Probleme
eingesetzt wird, wurde in den 20er Jahren von den Mathematikern Alfred James Lotka und
Vito Volterra unabhängig voneinander entwickelt. Sie formulierten drei Regeln, die so
genannten Volterra- oder auch Lotka-Volterra-Regeln. Die Berechnungen erfolgen mit Hilfe
von Differentialgleichungen, auf die hier nicht weiter eingegangen werden soll.
Ein anschauliches Beispiel für das Räuber-Beute-Modell, welches in Lehrbüchern gerne
angeführt wird, stellen die Fangaufzeichnungen der neufundländischen Hudson-Bay
Company dar. Diese führte über 90 Jahre Aufzeichnungen über die Menge an eingehenden
Luchs- und Schneehasenfelle. Dieses Beispiel eignet sich sehr gut zur Veranschaulichung
des Modells, da Neufundland ein artenarmes Ökosystem bietet, das heißt, dass nur
vergleichsweise geringe Störfaktoren auf die Entwicklung der Räuber- (Luchse) und
Beutepopulation (Schneehasen) wirken. Aus den Aufzeichnungen ergibt sich eine Periode
von knapp 7 Jahren.2
1 http://de.wikipedia.org/wiki/R%C3%A4uber-Beute-Beziehung
2 http://de.wikipedia.org/wiki/Volterra-Regeln
Räuber-Beute-Simulation
-3-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
1.3 Die Erweiterbarkeit des Modells
Ich habe mich für meine Simulation auf folgende Einflüsse beschränkt:
– Der Beutepopulation steht unbegrenzt Nahrung zur Verfügung.
– Die Räuber sterben nach x Simulationsschritten ohne Nahrung an Hunger.
– Beide Tierarten haben keine maximale Lebensdauer.
– Die Tiere produzieren ein neues Exemplar ihrer Art (Fortpflanzung) in einem
einstellbaren Alter (nach x Simulationsschritten).
Da in der Natur häufig viele Faktoren Einfluss auf das Wachstum einer Population haben,
lässt sich dieses Modell vielfältig erweitern. Die Beute könnte beispielsweise Räuber einer
weiteren Population sein oder die Fortpflanzung der Tiere könnte auf komplexere Weise
realisiert werden, was zum einen den Zeitpunkt der Fortpflanzung und zum anderen die
Anzahl der Nachkommen betrifft. Außerdem könnte den Beutetieren auch beim
Aufeinandertreffen mit einem Räuber eine Überlebenschance (Flucht) eingeräumt werden.
2. Das Programm – Anwenderinformationen
2.1 Inhalt des Datenträgers
Der Datenträger enthält folgenden Verzeichnisbaum:
–
–
–
–
–
Dokumentation
– Diese Dokumentation in verschiedenen Dateiformaten
Praesentation
– Die Präsentation des Projektes in verschiedenen Dateiformaten
source
– RoadRunner
– doc
– JavaDoc-Dokumentation (Ansehen über index.html möglich)
– gui
– Java Quellcodedateien der Grafischen Benutzeroberfläche
– img
– Bilder, die vom Programm verwendet werden
– logic
– Java Quellcodedateien des Räuber-Beute Algorithmus
– obj
– Objektdateien der 3D Modelle sowie deren Texturen
jar
– Ausführbares JAR-Archiv des Programmes
maya
Räuber-Beute-Simulation
-4-
Systemprogrammierung WS 06/07 HS-Fulda
–
Dirk Fidorski 618732
Modelldateien aus Maya 8.0
2.2 Systemvoraussetzungen und Installation
Zur Benutzung des Programmes wird eine installierte Java Laufzeitumgebung (Java
Runtime Environment / JRE) ab Version 5 benötigt.
Weiterhin wird ein installiertes Java3D-Paket ab Version 1.4 für die 3D-Ausgabe
vorausgesetzt.
Die 3D-Ausgabe benötigt eine recht hohe Rechenleistung, daher möchte ich als minimale
Taktfrequenz des Rechners ca. 1800Mhz angeben. Damit das Fenster komplett angezeigt
werden kann, muss die Bildschirmauflösung mindestens 1280x1024 Pixel betragen.
Für einen Schnellstart des Programmes habe ich im Ordner „jar“ der beiliegenden CD ein
JAR-Archiv bereitgestellt. Dieses ist vorkompiliert und somit direkt von der CD lauffähig. In
der Kommandozeile kann dieses mit dem Befehl „java -jar RoadRunner.jar“ gestartet
werden. In Microsoft Windows ist ein Start mit simplem „Doppelklick“ auf die Datei
„RoadRunner.jar“ möglich.
Zur Installation des Programmes muss der Ordner „\source\RoadRunner“ mit allen
Unterverzeichnissen und Dateien von der beiliegenden CD auf den gewünschten
Zielrechner kopiert werden. Diese Programmversion muss nun noch kompiliert werden.
Hierzu wechseln Sie bitte nach dem Kopiervorgang in den Ordner „RoadRunner“ und
führen die Datei „kompiliere.bat“ aus. Nachdem das Programm kompiliert wurde kann es
mit „RoadRunner.bat“ gestartet werden. (Der Pfad zum Compiler muss in der PATHVariable des Systems gesetzt sein)
Diese Batch-Dateien können in der Kommandozeile eingegeben, oder in Microsoft
Windows durch „Doppelklick“ gestartet werden.
In der Unix-Welt sind die Dateien analog einem Shell-Skript ausführbar (./kompiliere.bat
bzw. ./RoadRunner.bat). Hierbei bitte auf die benötigten Ausführungsrechte achten.
Eine weitere Möglichkeit ist es den Ordner „RoadRunner“ in eine Programmierumgebung
zu laden. Im Falle der freien Entwicklungsumgebung „eclipse“ ist dies über die
„Import“-Funktion möglich. Damit die Java3D Funktionen von eclipse erkannt werden
muss sichergestellt sein, dass die Bibliotheken „j3dcore.jar“, „j3dutils.jar“ und
„vecmath.jar“ dem so genannten „build-path“ des Projekts hinzugefügt wurden.
Dies ist beispielsweise an den Solaris-Sparc-Systemen der Hochschule Fulda zu prüfen.
2.3 Funktionsumfang und Bedienung
Das Hauptfenster des Programms teilt sich logisch in drei Bereiche. Der linke Rand bietet
verschiedene Einstellungsmöglichkeiten und die Möglichkeit zum Starten der gewünschten
Simulation. Im rechten oberen Bereich wird die Simulation je nach Einstellung zwei- oder
dreidimensional visualisiert. Der rechte untere Bereich zeigt während der Simulation die
Räuber-Beute-Simulation
-5-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Wachstumskurven der beiden Populationen.
Räuber-Beute-Simulation
-6-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Dem Anwender stehen im linken Bereich folgende Bedienelemente zur Verfügung:
Knopfgruppe „Feldgroesse“:
Nur im 2D-Modus veränderbar. Bestimmt die Größe des
Gebiets auf welchem die Simulation stattfindet.
Schieberegler „Beutetiere“:
Initialisierungswert für die Größe der Beutepopulation. Die
Summe aus Beute- und Raubtieren darf die Größe des
eingestellten Gebiets nicht übersteigen. Daher wird
gegebenenfalls automatisch zurück geregelt.
Schieberegler „Raubtiere“:
Initialisierungswert für die Größe der Räuberpopulation. Die
Summe aus Beute- und Raubtieren darf die Größe des
eingestellten Gebiets nicht übersteigen. Daher wird
gegebenenfalls automatisch zurück geregelt.
Schieberegler „Fortpflanzwert der Beutetiere“:
Gibt an wie viele Runden ein Beutetier existieren muss, um
ein neues Beutetier zu produzieren.
Schieberegler „Fortpflanzwert der Raubtiere“:
Gibt an wie viele Runden ein Raubtier existieren muss, um
ein neues Raubtier zu produzieren.
Schieberegler „Ueberlebenswert der Raubtiere“:
Gibt an wie viele Runden ein Raubtier ohne ein Beutetier zu
verspeisen überleben kann. Findet es im angegebenen
Intervall keine Nahrung, stirbt es an Hunger.
Knopf „Start“ / „Stop“:
Startet die Simulation mit den eingestellten Werten.
Während der Simulation, kann sie durch nochmaliges
Drücken des Knopfes gestoppt werden.
Knopf „Zur 2D/3D-Ausgabe wechseln“:
Wechselt in den entsprechenden Darstellungsmodus, die
Simulationswerte (außer der Feldgrösse) können wie
gewohnt eingestellt werden und über den Startknopf kann
eine Simulation gestartet werden.
Räuber-Beute-Simulation
-7-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
3. Die Programmentwicklung
3.1 Überblick – die verwendeten Techniken
Als Programmiersprache für das Simulationsprogramm habe ich Java in der Version 1.6
verwendet, sowie eclipse 3.2.1 als Programmierumgebung. Für die grafische Gestaltung
des Programms wurden die Klassen und Methoden des AWT-Toolkits, sowie Komponenten
der Swing-Dialogelemente verwendet. Der 3D-Anzeigebereich wurde mit Java3D Version
1.5 erstellt und gestaltet. Die eingesetzten 3D-Modelle wurden zuvor mit dem 3DModellierungstool Maya 8.0 erstellt und werden zur Laufzeit als obj-Dateien in das
Programm importiert.
Zum besseren Verständnis des Programmcode habe ich eine JavaDoc Dokumentation
angefertigt. (siehe Punkt 2.1)
3.2 Programmierung des Räuber-Beute Algorithmus
3.2.1 Anforderungen an das Programm
Für die Räuber-Beute Simulation habe ich folgenden Kriterien entwickelt, welchen das
Programm in geeigneter Weise gerecht werden muss:
1. Die Tiere befinden sich in einem begrenzten Feld, sie können sich pro Zug in eine
der vier Himmelsrichtungen bewegen.
2. Beide Tierarten haben keine maximale Lebensdauer.
3. Beutetieren steht unbegrenzt Nahrung zur Verfügung.
4. Raubtiere ernähren sich von Beutetieren und sterben nach einer einstellbaren Zahl
an Simulationsschritten ohne Nahrung an Hunger.
5. Beutetiere bewegen sich nur auf freie Nachbarfelder. Gibt es mehrere freie
Nachbarfelder, wird zufällig entschieden wohin das Beutetier zieht. Gibt es kein
freies Nachbarfeld, so bleibt das Tier auf seinem Platz.
6. Raubtiere ziehen mit Priorität auf ein Nachbarfeld mit einem Beutetier, um dieses
zu verspeisen. Nur wenn kein Beutetier in Reichweite ist bewegt er sich auf ein
freies Nachbarfeld. Falls es mehrere mögliche Zielfelder gibt, entscheidet auch hier
der Zufall in welche Richtung sich der Räuber bewegt.
7. Die Tiere produzieren ein neues Exemplar ihrer Art (Fortpflanzung) in einem
einstellbaren Alter.
Räuber-Beute-Simulation
-8-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
3.2.2 Die Klassenstruktur
Die oben genannten Kriterien werden in meinem Programm in dem Package „logic“
implementiert. Hierzu habe ich folgende Klassenstruktur entwickelt:
– Tier
Vaterklasse zu Raeuber und Beute
– Raeuber
Eigenschaften eines Raubtiers
– Beute
Eigenschaften eines Beutetiers
– Welt
Universum in welchem das Feld und die Verhaltensregeln festgelegt
sind
– Simulation
Thread, der die Simulation, sowie die Ausgabe koordiniert
Die Klasse „Tier“
Die Klasse Tier ist abstrakt und stellt Methoden und Attribute zur Verfügung, welche ein
Tier, also sowohl Raubtier, als auch Beutetier benötigen. Hier wird festgehalten um
welches Tier es sich handelt, wie alt es ist, und ob es in einer Simulationsrunde bereits
gezogen wurde oder nicht.
Das Alter des Tieres wird verwendet um Kriterium 7 erfüllen zu können. Der Alterswert
wird mit dem einstellbaren Fortpflanzwert verglichen, und falls dieser erreicht ist wird ein
Nachkomme erzeugt.
Das Attribut in welchem festgehalten wird ob das Tier bereits gezogen wurde ist essentiell,
da hierdurch sichergestellt wird, dass ein Tier nur genau einmal pro Simulationsschritt am
Zug ist. Da das Feld in welchem sich die Tiere befinden wie ein Koordinatensystem
aufgebaut ist, kann durch Zeilennummer und Spaltennummer jedes Einzelfeld identifiziert
werden. Das Feld wird zeilenweise, Element für Element durchgearbeitet, daher ist jedes
Einzelfeld genau einmal an der Reihe. Wenn nun aber beispielsweise das Tier in [Zeile 1,
Spalte 1] an der Reihe ist, und sich nach unten zu [Zeile 2, Spalte 1] bewegt, fährt der
Algorithmus in Zeile 1 mit Feld [Zeile 1, Spalte 2] fort und gelangt später zu Feld [Zeile 2,
Spalte 1]. Hier befindet sich jedoch das Tier, das in dieser Runde erst zu diesem Feld
bewegt wurde, damit dieses nun nicht ein zweites Mal bewegt wird, muss dies zuvor
markiert werden.
Die Klasse „Raeuber“
Die Klasse Raeuber ist von der Klasse Tier abgeleitet und erbt daher dessen Methoden und
Attribute. Zusätzlich wird bei dem Raubtier, um Kriterium 4 gerecht zu werden, ein Attribut
eingeführt, welches die Simulationsrunden zählt in welchen es in Folge keine Nahrung zu
sich genommen hat.
Die Klasse „Beute“
Die Klasse Beute ist ebenfalls von der Klasse Tier abgeleitet und benötigt keine weiteren
Attribute.
Räuber-Beute-Simulation
-9-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Die Klasse „Welt“
Somit sind die Objekte, welche die Tierarten repräsentieren fertig implementiert. Diese
werden nun in der Klasse Welt verwendet. Sie beinhaltet sowohl das Feld in welchem die
Tiere sich befinden als auch den eigentlichen Räuber-Beute Algorithmus welcher das
Verhalten der Tiere steuert. Die einzigen Schnittstellen von Objekten dieser Klasse sind
eine Methode um das Feld mit der aktuellen Population zu erhalten (Zur grafischen
Ausgabe notwendig), sowie eine Methode um eine Simulationsrunde einzuleiten, alles
andere geschieht transparent.
Beim erzeugen eines Objekts der Klasse „Welt“ werden zunächst alle einstellbaren
Parameter übergeben. Diese sind die Ausmaße des Simulationsfeldes, die Anzahlen der
Tiere, die Fortpflanzwerte der Tiere, sowie die Dauer die ein Raubtier ohne Nahrung
überleben kann.
Anhand dieser Daten wird ein zweidimensionales Feld vom Typ „Tier“ mit den
angegebenen Maßen erstellt.
Der erste Schritt ist nun, dieses Feld mit den gewünschten Anzahlen an Raub- und
Beutetieren zu füllen. Hierzu habe ich einen Algorithmus entwickelt, der die Tierarten
zufällig auf das Feld verteilt. Das Prinzip hierbei ist ein zufälliges, freies Feld auszuwählen,
dieses zufällig mit einem Raub- oder Beutetier zu besetzen, die Anzahl verbleibender Tiere
anzupassen und wieder von vorne zu beginnen, bis alle Tiere ihren Platz haben.
Hiernach ist die „Welt“ initialisiert und bereit die Räuber-Beute Simulation durchzuführen
und rundenbasierend Ergebnisse zu liefern.
Aus dem Objekt kann man sich nun die aktuelle Population liefern lassen, eine
Simulationsrunde einleiten, sich die neue, aktualisierte Population liefern lassen, etc.
Eine Simulationsrunde im Detail:
Eine Simulationsrunde besteht aus dem Durchlaufen und Überprüfen jedes einzelnen
Elementes, wobei je nach Typ des Feldes verschiedene Folgeaktionen ausgeführt werden
müssen. Das Feld wird zeilenweise durchgearbeitet und jedes Element überprüft. Handelt
es sich um ein freies Feld wird ohne weitere Aktion fortgefahren, handelt es sich um ein
Tier, wird geprüft ob es bereits am Zug war, wenn nicht wird eine Hierarchie an Methoden
zur Bewegung des Tiers entsprechend seiner Art aufgerufen.
Diese Methoden passen zunächst die Attribute des Tiers an. Das Alter wird erhöht und das
Tier wird als „gezogen“ markiert.
Hiernach wird bei einem Räuber geprüft, ob seine Zeit ohne Nahrung den angegebenen
Überlebenswert erreicht hat, falls ja wird er entfernt, er ist verhungert. Danach wird nach
Beute in einem Nachbarfeld gesucht, wie dies genau geschieht wird später erläutert.
Wurde Beute gefunden rückt der Räuber auf dieses Feld und die Beute wird entfernt, der
Räuber hat die Beute verspeist. Konnte keine Beute auf einem Nachbarfeld gefunden
werden, wird ein freies Nachbarfeld gesucht und der Räuber zieht dorthin.
Bei einem Beutetier wird nur nach einem freien Nachbarfeld gesucht, wird dies gefunden
bewegt es sich dorthin.
Beide Tierarten bleiben auf ihrer Position stehen, falls es kein freies Zielfeld gibt. Konnte
das Tier ziehen wird jeweils geprüft ob es das Alter zur Fortpflanzung erreicht hat, indem
sein Attribut „alter“ mit dem aktuell geltenden Fortpflanzwert verglichen wird. Ist das Alter
erreicht, wird ein Nachkomme auf der Ursprungsposition, auf welcher das Vatertier vorher
Räuber-Beute-Simulation
-10-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
stand, erzeugt. Das Alter des Tieres wird im Falle der Fortpflanzung zurückgesetzt.
Die Suche eines Zielfeldes läuft in zwei Methoden ab. Die Erste liefert zu einem
angegebenen Element dessen vier Nachabarelemente. Hierbei muss beachtet werde, dass
ein Nachbar eines Randelementes auf der gegenüberliegenden Seite des Feldes liegt.
Dies ist analog dem Prinzip: „Die Welt ist eine Kugel“. Weiterhin werden die Koordinaten
der Nachbarfelder mithilfe eines Zufallszahlengenerators gemischt, damit die
Himmelsrichtung die ein Tier später einschlägt zufällig ist.
Mithilfe einer weiteren Methode kann die Art (Beute oder freies Feld) eines gesuchten
Feldes spezifiziert werden. Diese erhält die vier Nachbarkoordinaten und prüft diese auf
die angegebene Art. Wird die Feldart gefunden werden die Koordinaten des Elements
sofort zurückgeliefert. Da die Koordinatenpaare bereits vorher gemischt wurden, kann das
erste gefundene Paar direkt zurückgegeben werden.
Somit können die Methoden, welche den Zug eines Tieres durchführen nach einem Feld
angegebener Art suchen lassen und erhalten die Koordinaten des Zielfeldes zurück. Sollte
es kein passendes Zielfeld geben, ist die Rückgabe leer.
Die Klasse „Simulation“
Die Klasse Simulation koordiniert die Räuber-Beute Simulation und die grafische Ausgabe
als Thread. Der Thread wird von der grafischen Benutzeroberfläche gestartet, er erzeugt
eine Welt mit eingestellten Parametern und lässt sich hiernach das Populationsfeld liefern.
Dies übergibt er, je nach Ausgabeart (2D oder 3D), den entsprechenden Ausgabeklassen.
Nach der Ausgabe leitet der Thread eine neue Simulationsrunde ein. Damit die Simulation
in einer angenehmen Geschwindigkeit abläuft wird der Thread je nach Ausgabeart
schlafen gelegt und somit verzögert.
Die Folge von Ausgabe, Verzögerung und Einleiten einer neuen Simulationsrunde wird
durch eine Endlosschleife ständig wiederholt, bis der Thread abgebrochen wird.
3.3 Die Grafische Benutzeroberfläche
Anmerkung: Im Anhang finden Sie Screenshots der grafischen Benutzeroberfläche.
3.3.1 Programmierung des Haupfensters
Die Grafische Benutzoberfläche habe ich mithilfe des „Abstact Windowing Toolkit“ (kurz:
AWT) und den leichtgewichtigen Swing-Komponenten realisiert. Die Klassen sind im
package „gui“ zusammengefasst. Detaillierte Informationen über die genaue
Programmierung entnehmen sie bitte der „JavaDoc“-Dokumentation zum Programm.
Räuber-Beute-Simulation
-11-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Das Hauptfenster der Oberfläche ist in 4 Teilen realisiert:
– Reglerfeld
– Feld zur 2D/3D Umschaltung
– Ausgabefeld
– Feld zur Ausgabe der Populationskurven
Für den Benutzer verschmelzen das Reglerfeld und das Feld zur 2D/3D Umschaltung zu
einer Einheit.
Das Feld zur Umschaltung besteht nur aus einem Bild und einem Knopf, es ist in der
Klasse Fenster deklariert und wird dem Fenster im Konstruktor zugefügt. Für das Feld auf
welchem das Bild, welches das Ausgabefeld bedeckt während keine Simulation läuft, gilt
das gleiche. Für alle anderen Komponenten habe ich eigene Klassen erstellt. Das
Reglerfeld und das Feld zur Ausgabe der Populationskurven werden dem Hauptfenster
ebenfalls im Konstruktor hinzugefügt. Die entsprechenden Ausgabefelder für 2D und 3D
Ausgabe werden beim Start einer Simulation auf der dafür reservierten Fläche platziert
und bei Beendigung dieser auch wieder entfernt.
Besonderheiten der Grafischen Oberfläche sind beispielsweise die automatische
Anpassung der Reglerskala sobald die Feldgröße sich ändert. Dies geschieht durch einen
so genannten „Listener“ welcher die Änderung wahrnimmt und eine spezifizierte Methode
auslöst. Diese Methode passt nun die Skala des Räuber- und Beutereglers an. Der
Maximalwert für eine Tierart wird auf die Feldgröße gesetzt.
Eine weitere Besonderheit ist, dass die Regler sich automatisch an korrekte Werte
anpassen, falls der Benutzer den erlaubten Wertebereich überschreitet. Dies ist bei dem
Regler für die Anzahl der Raubtiere und dem der Beuteanzahl der Fall. Deren Maximalwert
ist immer die Feldgröße. Allerdings müssen sich Raub- und Beutetiere diese teilen. Das
heißt, falls die Feldgröße 25^2 beträgt stehen 625 einzelne Segmente zur Verfügung. 625
ist auch die maximal einstellbare Anzahl für jede Tierart. Hat man nun 400 Raubtiere
eingestellt darf man maximal 225 Beutetiere einstellen, es besteht jedoch die Möglichkeit
625 einzustellen. Wenn man den Beuteregler nun über die Anzahl von 225 hinaus
verschiebt, wird der Räuberregler um die enstprechende Anzahl verringert, damit
sichergestellt ist, dass die Feldgröße nicht überschritten wird. Diese automatische
Anpassung geschieht sowohl beim Räuberregler als auch umgekehrt beim Beuteregler.
Beim Knopfdruck zum Wechsel in den 3D-Ausgabemodus wird aus Gründen der
Performance und der Übersichtlichkeit die Einstellmöglichkeit für die Feldgröße deaktiviert
und diese konstant auf 15^2 gesetzt.
Der Knopf zum Starten der Simulation führt zu einer Methode welche alle
Einstellungsmöglichkeiten deaktiviert, den Wechsel zum entsprechenden Ausgabefeld
einleitet und ein Simulationsobjekt mit den eingestellten Parametern erzeugt. Bei diesem
Objekt handelt es sich um einen Thread, welcher auch gleich gestartet wird. Ab hier erhält
der Knopf die Aufschrift „Stop“ und wird zum Anhalten der Simulation benutzt. Beim
Stoppen wird der Thread abgebrochen und alle Regler und Einstellmöglichkeiten werden
wieder aktiviert. Zu beachten ist hier der Modus. Falls der 3D Modus aktiv ist, dürfen hier
die Knöpfe zur Einstellung der Feldgröße nicht aktiviert werden. Weiterhin wird das
Ausgabefeld wieder entfernt und das RoadRunner-Bild erscheint wieder.
Räuber-Beute-Simulation
-12-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
3.3.2 Ausgabe der Wachstumsfunktionen
Die Ausgabe der Population als Kurve habe ich über ein „Graphics“-Objekt realisiert.
Hierdurch werden Zeichenfunktionen bereitgestellt. Für die Kurvenausgabe nutze ich die
Methode „drawLine ()“, welche eine Linie mit der Breite von einem Pixel von einem Punkt
zu einem zweiten zeichnet. Mithilfe dieser Methode wird direkt in das Kurvenfeld
(„JPanel“) gezeichnet. Dies geschieht in der Methode „zeichne ()“ des „KurvePanel“. Dieser
Methode wird die aktuelle Population übergeben. Daraus wird die aktuelle Anzahl der
Tierarten errechnet. Die Linien, welche die Kurve bilden werden jeweils von der Anzahl der
Tierart im letzten Schritt zur aktuellen Anzahl der jeweiligen Tierart gezogen. Das heißt,
die Anzahl der Tierarten des letzten Schritts müssen in einer Klassenvariable
zwischengespeichert werden. Die Kurven werden je nach Feldgröße entsprechend skaliert.
3.3.3 Ausgabe der Population in 2D
Die Ausgabe der Population in 2D habe ich durch verschiedenfarbige Quadrate realisiert 1.
Dies geschieht in der Methode „zeichne2D ()“ der Klasse „AusgabePanel2D“. Auch hier
benutze ich ein „Graphics“-Objekt zum Zeichnen. Hierbei greife ich auf dessen Methode
„fillRect ()“ zurück. Diese spannt bei gegebenem oberen linken Eckpunkt sowie Breite und
Höhe ein Rechteck auf. Da für die Darstellung der Population Quadrate ein angenehmeres
Bild abgeben sind Höhe und Breite gleich. Weiterhin ist auch der Anzeigebereich, sowie
das Populationsfeld quadratisch. Daher kann in der Ausgabeklasse die Höhe und Breite der
farbigen Quadrate einfach berechnet werden indem man die Breite der Anzeigefläche
durch die Populationsfeldbreite teilt. Hat man diesen Wert ermittelt, so wird das
Populationsfeld der Reihe nach durchgegangen und je nach Element (Räuber, Beute oder
leeres Feld) ein Quadrat in der entsprechenden Farbe gezeichnet. Die Position der
Eckpunkte der Quadrate lässt sich durch die Position des Elements im Populationsfeld
multipliziert mit der Breite des Quadrates errechnen.
3.4 Java3D / Ausgabe der Population in 3D2
3.4.1 Aufbau der 3D-Ausgabe – Der Konstruktor
Die für die 3D-Ausgabe zuständige Klasse heißt „AusgabePanel3D“. Sie befindet sich
ebenfalls im Package „gui“.
Als Basis der Ausgabe verwende ich ein „SimpleUniverse“, dabei handelt es sich um ein
einfaches vorkonfiguriertes Basisuniversum, welches für diesen Fall völlig ausreichend ist.
1 Siehe: Anhang C
2 Siehe: Anhang D
Räuber-Beute-Simulation
-13-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Die Ausgabe erfolgt über ein „Canvas3D“-Objekt. Diesem wird das zuvor erstellte
„SimpleUniverse“ zugeordnet.
Der Konstruktor beinhaltet außer diesem Grundgerüst noch ein paar erste
Konfigurationen. So wird die Position der Kamera über die Methode „setzteKamera ()“ in
ihre Startposition gebracht und es werden die benötigten Objekte geladen und zusammen
mit dem Simulationsfeld in einzelnen Branchgroups bereitgestellt.
3.4.2 Die Teilgraphen
Die Teilgraphen „bg_Beute“ und „bg_Raeuber“
Diese beiden Teilgraphen werden über die Methode „ladeObjekt ()“ erstellt. In dieser
Methode wird das jeweilige 3D-Objekt aus dem Dateisystem importiert und dem Graphen
hinzugefügt. Danach wird das Objekt so transformiert, dass es sich später in der oberen
linken Ecke des Simulationsfeldes befindet. Das Laden der 3D-Objekte erfolgt mit dem so
genannten „ObjektLoader“ von Java3D, auf diesen wird später noch ausführlich
eingegangen.
Der Teilgraph „bg_Figuren“
„bg_Figuren“ enthält zu jedem Simulationsschritt die vorhandenen Objekte vom Typ
Räuber und Beute. Gibt es zu einem Simulationszeitpunkt beispielsweise 10 Räuber und 12
Beutetiere, so enthält der Teilgraph 10 Teilgraphen des Typs „bg_Raeuber“ und 12
Teilgraphen des Typs „bg_Beute“. Jeder dieser Teilgraphen ist dabei so transformiert, dass
er auf dem Simulationsfeld an der Stelle erscheint, die seinen Koordinaten in der
Simulation entspricht.
Der Teilgraph „bg_Wueste“
In diesem Teilgraph befindet sich die Welt in der die beiden Populationen existieren.
Die Wüste, also das Feld auf dem die Tiere leben, wird aus einem Quader gebaut. Java3D
bietet für solche einfachen Formen so genannte „geometrische Primitive“. Für das
erstellen eines Quaders gibt es das Primitiv „Box“, welches ich hier verwendet habe. Der
Wüste wird noch ein Aussehen zugewiesen, welchem ein Farbattribut zugewiesen wurde,
wodurch die Wüste braun dargestellt wird.
Des weiteren wird dem Teilgraph eine Lichtquelle hinzugefügt. Ich verwende hierfür eine
direktionale Lichtquelle, diese eignet sich hier aus mehreren Gründen sehr gut. Zum einen,
weil das von ihr geworfene Licht im Gegensatz zu beispielsweise ambientem Licht eine
Richtung hat und somit Schatten wirft, welcher die importierten 3D-Objekte gut zur
Geltung bringt. Zum Anderen hängt die Intensität des Lichts nicht vom Abstand zum
beleuchteten Objekt ab.
Zuletzt erhält der Teilgraph noch einen Hintergrund. Diesem wird als Hintergrundfarbe die
Farbe des Hauptfensters zugewiesen.
Räuber-Beute-Simulation
-14-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
3.4.3 Die Simulation
Der Bau der Ausgabe eines Simulationsschritts erfolgt in der Methode „zeichne3D ()“
Die Methode bekommt als Parameter ein Populationsfeld übergeben und wird im
Simulations-Thread nach jedem Simulationsschritt aufgerufen. Das Populationsfeld wird
durchlaufen und jedes Element wird auf seinen Typ geprüft. Diesem entsprechend werden
dann die Räuber- und Beutefiguren erzeugt und mittels einer geeigneten Transformation
auf ihren Platz verschoben. So wird Stück für Stück ein temporärer Teilgraph
zusammengesetzt, welcher alle Tiere auf ihrer vorgesehenen Position enthält. Ist dieser
vollständig, wird sein Inhalt in den zuvor vom Universum entfernten Teilgraphen
„bg_Figuren“ zugewiesen. Danach wird dieser Teilgraph dem Universum wieder
zugeordnet.
3.4.4 Die Kamera – Optionen zur Laufzeit
Im oberen Bereich des 3D-Anzeigebereichs befinden sich zwei Knöpfe mit denen sich der
Blick auf das 3D-Feld verändern lässt. Der Blickwinkel auf die Szene wird durch die
Position der Kamera in der Szene geregelt. Drückt der Anwender auf einen der beiden
Knöpfe wird die Methode „setzeKamera ()“ mit entsprechenden Parametern, aus welchen
die Position und Ausrichtung der Kamera berechnet wird, aufgerufen. Die Methode
erwartet drei Parameter vom Typ „float“. Die ersten beiden Parameter bezeichnen die yund z-Koordinate der Kamera (die x-Koordinate ist fest gesetzt und verändert ihren Wert
nicht). Aus den drei Koordinaten wird in der Methode ein Vektor gebildet, welcher als
Translation auf die Kamera angewendet wird und somit die Position der Kamera im Raum
beschreibt. Der dritte Parameter bestimmt die Rotation der Kamera um die x-Achse.
Die beiden erzeugten Transformationen Translation und Rotation werden vereinigt und auf
die Kamera des Universums angewandt.
4. Die Modelle / 3D-Modellierung mit Maya
4.1 Die Modellierungssoftware
Für die Modellierung der 3D-Objekte habe ich mich gegen eine direkte Modellierung in
Java3D und für die Nutzung einer speziellen Modellierungssoftware entschieden. In
Java3D stehen dem Entwickler zwar auch unzählige Möglichkeiten zur Modellierung
komplexerer Strukturen zur Verfügung, jedoch fällt es mit einer speziellen Software sehr
viel einfacher anschauliche Ergebnisse zu erzielen. In Java3D müssen alle Knoten und
Kanten des Modells über die Angabe von Werten gesetzt und angeordnet werden. Zum
anderen kann das Modell nur im laufenden Programm betrachtet werden. Möchte man
beispielsweise die Rückseite des Modells betrachten, muss man dieses zunächst
entsprechend transformieren. Eine 3D-Modellierungssoftware bietet hier einen wesentlich
höheren Komfort.
Räuber-Beute-Simulation
-15-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Als Nächste stellte sich die Frage, welche Software zum Einsatz kommen sollte. Zur
Auswahl standen das in den Übungen bereits vorgestellte Lightwave der Firma Newtek
und das Programm Maya von Autodesk vormals Alias. Da ich mit Lightwave gut zurecht
gekommen bin, war ich neugierig wie leicht mir der Umstieg zu einer anderen Software
fallen würde. Ich vermutete, dass es mit dem Umstieg von einer Programmiersprache zu
einer anderen vergleichbar sein könnte.
Aus diesen Gründen und weil ich nach dem Studium sicherlich nicht mehr so einfach die
Möglichkeit bekommen werde mich mit diesem Programm zu beschäftigen, entschied ich
mich für die Entwicklung der Modelle in Maya Version 8.0 wie sie auf den Rechnern der
Hochschule zur Verfügung steht.
4.2 Die Modelle
Bei meinen Überlegungen nach geeigneten Tieren für die Simulation stieß ich zunächst auf
die klassischen Modelle: Luchse und Schneehasen, Haie und Fische, etc.
Dabei eröffnete sich ein erstes Problem. Für eine sinnvolle Simulation des Modells musste
das Simulationsfeld eine Mindestgröße von 15x15 Feldern aufweisen. Daraus ergibt sich
jedoch, dass die Modelle nur recht klein ausgegeben werden können. Je kleiner jedoch das
Modell umso schwieriger fällt es Details im Modell zu erkennen. Aus dieser Überlegung
wuchs die Idee keine realistischen Tiermodelle zu erstellen, sondern Modelle im Comicbzw. Cartoonstil zu verwenden, da diese im Normalfall weniger Details aufweisen.
Zunächst wollte ich diese Modelle selbst entwickeln, also beispielsweise einen eigenen
Comic-Hasen entwerfen, doch dann fielen mir die alten Roadrunner-Kurzfilme von Warner
Bros. ein. Da diese Cartoons für mich den Inbegriff der ewigen Jagd des Räubers nach
seiner Beute darstellen, habe ich mich dazu entschieden, die beiden Hauptcharaktere für
meine Modelle zu verwenden. Der Roadrunner symbolisiert die Beute und der Kojote Wile
E. Coyote den Räuber.
Um eine harmonische und nicht zu überladene Darstellung zu erreichen entschied ich mich
außerdem, nicht den gesamten Körper der Figuren zu modellieren. Angelehnt an die
Figuren in einem Schachspiel habe ich lediglich den Kopf modelliert und diesen auf einer
Art Ständer bestehend aus einer quadratischen Grundfläche und einem Zylinderförmigen
Stab, welcher als eine Art Hals den Kopf mit der Grundfläche verbindet, befestigt.
Als Vorlage für die Modellierung der Köpfe dienten mir mehrere Bilder bzw.
Schnappschüsse von Szenen aus den Roadrunner-Cartoons, auf die ich bei meinen
Internetrecherchen gestoßen bin1.
1 http://www.freewebs.com/supergenius/Wile%20E.%20Coyote%20and%20Roadrunner.JPG
http://members.aol.com/lovelandrunners/graphics/roadrunner.jpg
http://skyblue.gen.tr/img/roadrunner.jpg
Räuber-Beute-Simulation
-16-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
4.2.1 Die Beute – Der Roadrunner1
Bevor ich mit der Modellierung des Kopfes begonnen habe, habe ich die verfügbaren
Bilder des Roadrunners eingehend studiert um die charakteristischen Gesichtsmerkmale
des Vogels herauszufinden. Die Kopfform des Roadrunners ist eine Kugel und die Augen
sind typisch für Cartoonfiguren, nämlich ein großes weißes Oval mit einem kleinen
schwarzen Oval im Inneren als Pupille. Außerdem besteht der gesamte Kopf des
Roadrunners aus einer einzigen Farbe. Unverwechselbar wird der Kopf durch zwei
Merkmale auf deren Modellierung ich im folgenden Näher eingehen werde. Diese
Merkmale sind zum einen die Form des Schnabels und zum anderen der Federschopf den
er auf dem Kopf trägt.
Grundgerüst
Als erstes habe ich den „Ständer“ modelliert, auf den der Kopf des Roadrunner und später
auch der des Kojoten befestigt werden soll. Die Grundfläche bildet ein Polygon-Quader mit
quadratischen Bodenfläche. Auf diesen Quader habe ich eine „Lattice-Box“ gelegt. Eine
Lattice-Box dient zur Verformung von Körpern oder von markierten Teilflächen indem sie
den markierten Bereich mit einer Box, welche an den Ecken mit verschiebbaren Knoten
versehen ist, umgibt. Die Veränderungen die an der Box vorgenommen werden, werden
dann entsprechend auf die Flächen im Inneren umgerechnet. Nachdem man mit den
Änderungen fertig ist, kann man die Abhängigkeit der Lattice-Box von der markierten
Fläche durch löschen der „History“ des Objekts aufheben und die Lattice-Box
verschwindet. Im Falle der Grundfläche habe ich die Lattice-Box verwendet um die obere
quadratische Fläche etwas zu verkleinern und die „Platte“ somit an den Rändern
abgeschrägt darzustellen.
Der Stab, der die Grundfläche mit dem jeweiligen Kopf verbinden soll ist ein PolygonZylinder welchen ich in der Mitte der Grundfläche platziert habe. Zuletzt können die beiden
erstellten Polygone mit Hilfe der Kombiniere-Funktion zu einem Objekt vereint werden.
Der Kopf
Wie oben erwähnt besteht der Kopf zunächst nur aus einer Kugel, welcher ich als Farbe
blau zugewiesen habe. Etwa in der Mitte der Kugel habe ich die beiden Augen angebracht.
Dazu habe ich eine Kugel zu einem großen, platten Oval verformt und eine weitere zu
einem kleinen Oval. Dem großen Oval habe ich als Farbe Weiss und dem kleinen Schwarz
zugewiesen und das Kleine im unteren Rand des Großen positioniert. Dann habe ich beide
Ovale markiert und mit dem Befehl „Mirror Geometrie“ an der y-Achse gespiegelt, damit
die Augen identisch geformt sind.
1 Siehe: Anhang E
Räuber-Beute-Simulation
-17-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Der Schnabel
Bei der Modellierung des Schnabels bin ich auf einige Probleme gestoßen und habe
deshalb von allen Modellierungsarbeiten für diese am meisten Zeit benötigt.
Auf den Bildern die mir als Vorlagen zur Verfügung standen war der Schnabel sehr
unterschiedlich abgebildet. Je nach benötigtem Gesichtsausdruck wurden hier großzügige
Änderungen der Schnabelform vorgenommen. Vor allem schienen Seiten- und
Frontansichten nicht immer logisch zueinander zu passen. Daher musste ich verschiedene
Formen ausprobieren bis ich zu einem zufriedenstellenden Ergebnis kam.
Ein weiteres Problem war, dass ich auf einen gleichmäßigen, geschwungenen Verlauf des
Schnabels großen Wert legen wollte, denn dies ist ein wichtiges Kriterium bei
Cartoonfiguren. Leider wurden meine Versuche Polygon-Primitive als Grundlage zu
nehmen und sie „per Hand“, also durch verschieben der Knoten, Kanten und Flächen, zu
einem Schnabel zu verformen nicht gleichmäßig genug. Dieses Problem hätte ich durch die
„Smooth“-Funktion einigermaßen lösen können, jedoch erhöht sich durch diese Funktion
auch die Komplexität des Objekts und damit die Größe der später zu importierenden Datei.
Daher habe ich mich für einen anderen Weg entschieden.
Ich hatte mich schon ein wenig mit den so genannten „NURBS“-Primitiven beschäftigt.
Diese haben in Maya einen recht hohen Stellenwert. Die Abkürzung NURBS steht für NonUniform Rational B-Splines und es handelt sich bei ihnen um mathematische Kurven die
beliebige Formen wie komplexe 3D-Körper, 2D-Flächen oder auch Linien darstellen
können. Die Technik wurde in der Vergangenheit hauptsächlich in CAD-Programmen
verwendet, mittlerweile werden sie von fast allen gängigen Grafikprogrammen
unterstützt1.
Um eine gleichmäßige Schnabelform zu erreichen habe ich mit NURBS-Kreisen und der
Methode „Loft“ gearbeitet. Bei dieser Methode erstellt man anhand der Kreise
Querschnitte des gewünschten Objekts. Die Kreise werden dazu über ihre Knoten zu dem
entsprechenden Querschnitt verformt und übereinander in dem gewünschten Abstand und
der gewünschten Reihenfolge angeordnet. Danach werden die Querschnitte in
fortlaufender Reihenfolge markiert, damit auf sie die Funktion „Loft“ angewandt werden
kann. Daraufhin errechnet Maya einen gleichmäßigen Verlauf zwischen den benachbarten
Querschnitten und bildet so ein NURBS-Objekt welches alle Querschnitte durchläuft. Das
Objekt kann daraufhin in ein Polygon-Objekt umgewandelt und bei Bedarf mit den
bekannten Polygonwerkzeugen weiter modelliert werden. Da ich diese Methode jedoch
gewählt habe um den Schnabel nicht per Hand modellieren zu müssen, war in diesem Fall
keine weitere Veränderung mehr notwendig. Ich habe den Schnabel lediglich in der Größe
angepasst und unterhalb der Augen am Kopf angebracht. Danach habe ich dem Schnabel
ein kräftiges Gelb als Farbe zugewiesen.
Der Schopf
Der Schopf des Roadrunners ist ein langer Federbusch an der Rückseite seines Kopfes. Die
Abmessungen der Köpfe der Modelle sollen die Abmessungen der Grundfläche des
Ständers jedoch nicht übersteigen, um eine einheitliche Größe sicherzustellen. Aus diesem
Grund ist der Schopf in diesem Modell entsprechend verkürzt modelliert, was jedoch nicht
1 http://www.de.rhino3d.com/nurbs.htm
Räuber-Beute-Simulation
-18-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
weiter ins Gewicht fällt. Erstellt habe ich die Grundform des Schopfes am Hinterkopf des
Roadrunner aus einem Polygon-Zylinder mit abgerundeten Ecken. Die grobe Form der
einzelnen Federn habe ich durch verschieben einzelner Knoten modelliert. Danach habe
ich mehrfach mit der Lattice-Box einzelne Knotengruppen des Schopfes nachbearbeitet.
Den fertigen Schopf habe ich an der Rückseite des Kopfes angebracht und ihm die gleiche
Textur wie dem Kopf zugewiesen. Danach habe ich den Schopf und den Kopf zu einem
Objekt zusammengefügt.
4.2.2 Der Räuber – Wile E. Coyote1
Auch hier stellte sich wieder die Frage, welche Gesichtsmerkmale charakteristisch für das
Erscheinungsbild des Kojoten sind. Die folgenden Merkmale wollte ich in meine
Modellierung einbinden:
– Die lange, etwas wellige Nase mit der schwarzen Kugel am Ende
– Die langen, hasenähnlichen Ohren
– Der breite und farblich abgesetzte Wangen- / Bartbereich
– Die Augenbrauen
– Zerzaustes Fell im Gesicht, an den Ohren und den Augenbrauen
Auf die halb geschlossenen Augenlider habe ich bewusst verzichtet, da ich fürchtete sie
würden bei der geringen Größe der Modelle kaum sichtbar sein und im schlimmsten Fall
wären die Augen als solche nicht mehr zu erkennen gewesen. Da im Nachhinein selbst die
Augenbrauen kaum zu erkennen sind, war dieser Schritt wohl vernünftig.
Hier nun die einzelnen Modellierungsschritte im Überblick:
Grundgerüst:
Als Basis für die Modellierung habe ich die Grundform des Roadrunners, also den Ständer
mit der Kugel als Kopf und den Augen, verwendet. Die restlichen Elemente des
Roadrunners wurden entfernt und dem Ständer und der Kopfform wurden entsprechende
Farben zugewiesen.
Der Wangenbereich:
Um die Kopfform des Kojoten zu erhalten kombinierte ich die schon vorhandene Kugel mit
einer weiteren, zu einem liegenden Oval verformten Polygonkugel. Dem Oval habe ich
durch wiederholtes Drehen und Verschieben der Knoten am linken und rechten Rand eine
leicht gebogene Form gegeben. Die Fransen an den Seiten habe ich sozusagen „per
Hand“, also durch Markieren und Verschieben der entsprechenden Knoten des Ovals,
herausgearbeitet. Diese Technik findet an allen Stellen statt, an denen der Kojote ein
zerzaustes Fell vorweisen soll.
1 Siehe: Anhang F
Räuber-Beute-Simulation
-19-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Die Nase:
Wile E. Coyote hat eine lange, runde, gebogene Nase, daher habe ich ein Kegel-Primitiv
als Grundform gewählt, allerdings musste der Kegel etwas verbreitert werden um der
Nasenform des Kojoten gerecht zu werden. Die charakteristischen Biegungen in der Nase
habe ich durch Wellen am Rand angedeutet. Die Länge der Nase durfte jedoch die
Abmessungen des Ständers nicht übersteigen, damit sich die Abmessungen des Modells im
Vergleich zu denen des Roadrunners nicht verändern. Dies fällt aber beim Gesamteindruck
nicht weiter auf.
Zuletzt fehlt der Nase nur noch die typische schwarze Kugel auf der Spitze.
Die Ohren:
Als Grundform für die Ohren dient ein Zylinder. Die Knoten an der oberen Kreisfläche des
Zylinders habe ich mittels des Tools „Merge“ zu einem Knoten verschmolzen, dadurch
laufen die Ohren spitz zu. Danach habe ich die Breite des Zylinders etwas erhöht und die
Tiefe verringert. Die Wölbung der Ohrmuschel nach innen, hab ich durch verschieben der
entsprechenden Flächen erreicht. Auch hier habe ich die beim Wangenbereich
beschriebene Technik zum Erzeugen von zerzaustem Fell verwendet. Nachdem ich so das
linke Ohr modelliert hatte, habe ich es mittels der Methode „Mirror Geometrie“ an der yAchse gespiegelt und das Ohrenpaar am Kopf positioniert.
Die Augenbrauen:
Die Augenbrauen sind aus einem Zylinder entstanden. Dem Zylinder wurde auf die gleiche
Art wie dem Wangenbereich eine leicht gebogene Form verliehen. Danach wurde der Rand
zerzaust und die fertige Augenbraue an der y-Achse gespiegelt.
Die Farbgebung:
Inspiriert von den Bildern des Kojoten wollte ich das Fell zweifarbig gestallten. Nachdem
ich verschiedene Kombinationen ausprobiert habe kam ich zu der folgenden Aufteilung:
–
–
Hellbraun:
Dunkelbraun:
Nase, Ohren, Wangen, Augenbrauen
Obere Kopfhälfte, Ständer
Normalerweise sind auch die Ohren des Kojoten zweifarbig, da ich das Modell jedoch nicht
mit Details überladen wollte habe ich hierauf verzichtet.
Räuber-Beute-Simulation
-20-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
4.3 Exportieren der Modelle
Da es in Java3D einen „ObjectLoader“ zum laden von Dateien im obj-Format gibt, erschien
es mir vernünftig die Modelle in diesem Format zur Verfügung zu stellen. Unter der
Standardkonfiguration von Maya ist die Option zum exportieren im obj-Format jedoch
deaktiviert, so dass das Dateiformat in der Liste des gewünschten Dateiformats nicht
aufgeführt wird. Im Plugin-Manager von Maya kann man die entsprechenden dll-Dateien
für den obj-Export aktivieren, woraufhin die Option des obj-Exports in die Liste der
Dateiformate aufgenommen wird. Exportiert man nun die Modelle, so erstellt Maya eine
obj-Datei, eine gleichnamige mtl-Datei und falls vorhanden Kopien der verwendeten Bilder
für Texturen. Die obj-Datei enthält die Daten zur Geometrie der exportierten Objekte und
die mtl-Datei verweist auf verwendete Texturen. Hier gibt es also eine Aufteilung in die
Teilbereiche Aufbau und Aussehen.
5. Der Object-Loader
5.1 Funktionsweise
Mithilfe des in Java3D integrierten Object-Loaders können 3D-Objekte aus Dateien im
Format obj als „Scene-Objekte“ importiert werden. Das Laden erfolgt über die Methode
„load“, die auf ein Objekt vom Typ ObjectFile angewandt werden kann. Als Parameter
erwartet die Methode eine URL mit der Adresse der zu ladenden Datei. Das so erzeugte
Scene-Objekt kann nun auf die selbe Art wie auch die in Java3D erzeugten Primitiven
einem Teilgraphen oder einer Transformationsgruppe zugewiesen werden.
5.2 Aufgetretene Probleme
Probleme gab es bezüglich der Kompatibilität der von Maya vorgenommenen und der von
Java3D erwartet Formatierung der obj-Dateien. Die in Maya vorgenommene Skalierung
hatte beispielsweise keinen Einfluss auf die Skalierung der in Java3D importierten Objekte.
Exportiert man ein Modell in Maya mit der 5-fachen Größe wie zuvor bleibt die Darstellung
in Java3D unverändert. Da Java in diesem Fall jedoch eine sich nicht verändernde
Standardgröße für die Objekte annimmt, stellt dies kein Problem dar. Die Skalierung in
Java3D ist nicht komplizierter wie die in Maya, daher kann sie auch nach dem Laden der
Modelle mit Hilfe einer Transformationsgruppe vorgenommen werden.
Ein weiteres Problem ergab sich mit den zugewiesen Texturen, dessen Ursache in der
Formatierung der mtl-Datei zu finden sein dürfte. Weist man den Modellen in Maya ein
Material mit einfachen Farbwerten zu, so wird das Objekt ohne Textur, also schwarz in
Java importiert. Weist man den in Maya verwendeten Materialien jedoch eine Textur in
Form einer Datei zu, funktioniert der Import korrekt und die angegebene Textur erscheint
Räuber-Beute-Simulation
-21-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
auf der Oberfläche der Modelle. Daher war die Lösung dieses Problems nicht schwer zu
finden. Ich habe für jede Farbe eine kleine jpg-Datei, die nur aus einer Fläche mit der
jeweiligen Farbe besteht, erstellt und diese Bilder den Modellen in Maya als Texturen
zugewiesen. Natürlich müssen die jpg-Dateien Java3D im gleichen Ordner wie die obj- und
die mtl-Dateien zur Verfügung gestellt werden.
6. Aufwandsdarstellung
6.1 Programmteil Java
Den reine Programmieraufwand des Algorithmus und der grafischen Oberfläche habe ich
mit 45 Stunden bemessen. Hierzu zählt auch das Sammeln von Informationen zu diesem
Thema.
6.2 Programmteil Java3D
Hier war der Aufwand wesentlich höher. Für den Java3D Teil habe ich ca. 40 Stunden
benötigt. Davon war ein enormer Teil die Recherche und das Lesen von Literatur, da ich
mich komplett in Java3D einarbeiten musste und nie zuvor damit gearbeitet hatte.
6.3 Programmteil Maya
Für die Modellierung der beiden Tiere habe ich etwa 5 Stunden benötigt. Der Schnabel des
Roadrunner fiel mir hierbei am schwersten. Die Einarbeitung in das Programm Maya
würde ich mit etwa 20 Stunden ansetzen. Durch das Arbeiten mit Lightwave an der
Hochschule konnte man leicht Gemeinsamkeiten der Programme erkennen.
Räuber-Beute-Simulation
-22-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
7. Quellen
[1] Wikipedia-Eintrag zur Räuber-Beute Beziehung
http://de.wikipedia.org/wiki/R%C3%A4uber-Beute-Beziehung
[2] Wikipedia-Eintrag zu den Volterra-Regeln
http://de.wikipedia.org/wiki/Volterra-Regeln
[3] Informationen zu Räuber-Beute Systemen zur Verifikation der Wikipedia Seiten.
http://www.globalchange.umich.edu
/globalchange1/current/lectures/predation/predation.html
[4] Informationen zu Räuber-Beute Systemen zur Verifikation der Wikipedia Seiten.
http://www.uni-protokolle.de/Lexikon/R%E4uber-Beute-Beziehung.html
[5] Java3D Einführung im PDF-Format als Freeware.
E-Book „Java3D 1.3 für Einsteiger und Fortgeschrittene“ von Michael Pfeiffer
[6] Guido Krüger - Handbuch der Java-Programmierung HTML-Ausgabe 4.0.3
http://www.javabuch.de/
[7] Umfangreiches Java Forum mit einem Unterforum für Java3D
http://forums.java.net
[8] Informationen zu NURBS
http://www.de.rhino3d.com/nurbs.htm
Räuber-Beute-Simulation
-23-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
8. Anhang
Anhang A: Klassendiagramm
Räuber-Beute-Simulation
-24-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Anhang B: Schnittstellendefinition
logic.Tier
Rückgabetyp
Methode
Parameter
Bemerkungen
void
alterHoch
()
Alter inkrementieren
void
alterReset
()
Alter auf Null setzen
int
getAlter
()
Liefert das Alter des Tiers
String
getTyp
()
Liefert den Typ des Tiers
void
jetztBewegt
()
Tier als bewegt markieren
void
resetBewegt
()
Tier auf nicht bewegt setzen
boolean
getNichtBewegt
()
Liefert ob Tier am Zug war
logic.Beute
Rückgabetyp
Methode
Parameter
Bemerkungen
void
alterHoch
()
Alter inkrementieren
void
alterReset
()
Alter auf Null setzen
int
getAlter
()
Liefert das Alter des Tiers
String
getTyp
()
Liefert den Typ des Tiers
void
jetztBewegt
()
Tier als bewegt markieren
void
resetBewegt
()
Tier auf nicht bewegt setzen
boolean
getNichtBewegt
()
Liefert ob Tier am Zug war
logic.Raeuber
Rückgabetyp
Methode
Parameter
Bemerkungen
void
alterHoch
()
Alter inkrementieren
void
alterReset
()
Alter auf Null setzen
int
getAlter
()
Liefert das Alter des Tiers
String
getTyp
()
Liefert den Typ des Tiers
void
jetztBewegt
()
Tier als bewegt markieren
void
resetBewegt
()
Tier auf nicht bewegt setzen
boolean
getNichtBewegt
()
Liefert ob Tier am Zug war
void
ohneNahrungHoch
()
Hungerzeit inkrementieren
void
ohneNahrungReset
()
Hungerzeit auf Null setzen
int
getOhneNahrung
()
Liefert Hungerrunden
Räuber-Beute-Simulation
-25-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
logic.Welt
Rückgabetyp
Methode
Parameter
Bemerkungen
Tier [ ] [ ]
getPopulation
()
Liefert Populationsfeld
void
simRunde
()
Nächster Simulationsschritt
logic.Simulation
Rückgabetyp
Methode
Parameter
Bemerkungen
void
run
()
Thread run-Methode
gui.Fenster
Rückgabetyp
Methode
Parameter
Bemerkungen
void
wechsleAPanel
(int)
Ausgabefeld austauschen
void
akt_bt_Umschalt
(boolean)
2D/3D-Knopf (de)aktivieren
boolean
get3D
()
Liefert den Ausgabemodus
void
zeichneKurve
(Tier [ ] [ ])
Gibt Wachstumsfunktion aus
void
resetKurveIndex
()
Kurven von vorne zeichnen
void
zeichneAusgabe2D
(Tier [ ] [ ])
2D-Ausgabe der Population
void
zeichneAusgabe3D
(Tier [ ] [ ])
3D-Ausgabe der Population
gui.BitmapComponent
Rückgabetyp
Methode
Parameter
Bemerkungen
void
paintComponent
(Graphics)
Methode zum Zeichnen
void
getPreferredSize
()
Liefert Größe der Kompon.
void
getMinimumSize
()
Liefert min. Größe
gui.ReglerPanel
Rückgabetyp
Methode
Parameter
Bemerkungen
void
akt_rbs_2D
()
Knöpfe Feldgröße aktivieren
void
deakt_rbs_2D
()
Knöpfe Feldgröße deaktiv.
gui.KurvePanel
Rückgabetyp
Methode
Parameter
Bemerkungen
void
zeichne
(Tier [ ] [ ])
Gibt Wachstumsfunktion aus
void
resetIndex
()
Kurven von vorne zeichnen
gui.AusgabePanel2D
Rückgabetyp
Methode
Parameter
Bemerkungen
void
(Tier [ ] [ ])
2D-Ausgabe der Population
zeichne2D
Räuber-Beute-Simulation
-26-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
gui.AusgabePanel3D
Rückgabetyp
Methode
Parameter
Bemerkungen
void
zeichne3D
(Tier [ ] [ ])
3D-Ausgabe der Population
gui.Hauptklasse
Rückgabetyp
Methode
Parameter
Bemerkungen
void
main
(String [ ])
Main-Methode
Räuber-Beute-Simulation
-27-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Anhang C: 2D-Simulation
Räuber-Beute-Simulation
-28-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Anhang D: 3D-Simulation
Räuber-Beute-Simulation
-29-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Anhang E: Render View Roadrunner
Räuber-Beute-Simulation
-30-
Systemprogrammierung WS 06/07 HS-Fulda
Dirk Fidorski 618732
Anhang F: Render View Wile E. Coyote
Räuber-Beute-Simulation
-31-