Interaktive 3D-Stellarkartographie

Werbung
Interaktive
3D-Stellarkartographie
Studienarbeit
vorgelegt von
Thomas Jegust
Institut für ComputerVisualistik
Arbeitsgruppe Computergraphik
Betreuer: Dipl.-Inform. Matthias Biedermann
Prüfer: Prof. Dr.-Ing. Stefan Müller
Mai 2005
2
Inhaltsverzeichnis
1. Einleitung
04
2. Theoretische Grundlagen
2.1 Sterne vs. Planeten
2.2 die solare Nachbarschaft
2.3 Sternörter und Koordinaten
2.4 Entfernungsmessung über große Distanzen
2.5 Spektralklassen
2.6 Binär- und Trinärsternsysteme
05
05
07
07
08
09
09
3. Billboards
3.1 Rotationsachsen
3.2 Darstellung der Sterne als VABB
3.3 Zwei Varianten zur Darstellung
3.3.1 Variante 1
3.3.2 Variante 2
10
10
11
12
12
13
4. Beschreibung des Programms
4.1 Daten
4.2 Star-Objekte
4.2.1 Umrechnung in kartesische Koordinaten
4.3 Parsen der Textdateien
4.4 Aufbau des Szenegraphen
4.4.1 Die Methode createStar
4.4.2 Die Methode createSystem
4.4.3 Skalierung der Sterne
4.5 Einfügen eines Skybackgrounds
4.6 Navigation
4.6.1 Oben/Unten im Weltraum
4.6.2 Einbinden einer eigenen Navigation
4.7 Picking
4.8 Einblenden von Informationen
4.9 Diverse Effekte
4.9.1 FTL-Effekt
4.9.2 Animierte Billboards
4.9.3 Selektierte Sterne
4.9.4 Bildschirmschoner
14
14
15
15
16
18
19
21
24
26
28
28
29
31
33
35
35
37
39
39
5 Einbinden als Stereoapplikation
40
6 Ausblick
41
7 Fazit
42
8
Quellenverzeichnis
43
3
1. Einleitung
Der Blick in den Nachthimmel offenbart dem Betrachter ein Bild der Sterne und anderer
Himmelskörper jenseits der Grenzen unseres Sonnensystems. Allerdings gehen hier
aufgrund der überaus hohen räumlichen Distanzen zu den Nachbargestirnen die
dreidimensionalen Informationen für das menschliche Auge verloren. Die Entfernung
eines Sterns zum Betrachter kann ohne weitere technische Hilfsmittel nicht eingeschätzt,
geschweige denn mit anderen bekannten Entfernungen in Beziehung gebracht werden.
Mit Hilfe der Computergrafik ist es möglich, ein Modell des interstellaren Raumes im
Umkreis von 20 Lichtjahren (ca. 188 Billionen km) in so stark verkleinertem Maßstab
anzufertigen, dass die dreidimensionalen Informationen für den Betrachter leicht
ersichtlich werden und somit diesem eine neue Sicht und ein neues Verhältnis zu unserer
Lage im Weltraum offenbaren.
Ziel der Arbeit ist es eine für den Endanwender leicht und intuitiv zu bedienende,
ansprechende Software zu gestalten. Aufbauend auf Informationen aus der Astronomie
soll jene Software einerseits korrekte Daten der
umliegenden Gestirne liefern,
andererseits diese aber in publikumswirksamer Form präsentieren – die Zielgruppe sind
astronomische Laien sowie Hobby-Astronomen.
Die Umsetzung erfolgt mittels der Programmiersprache C++ unter Verwendung von
OpenSG.
4
2. Theoretische Grundlagen
In den folgenden Abschnitten sollen zunächst einige theoretische Grundlagen der
Astronomie dargelegt und ihre jeweilige Umsetzung im Programm beschrieben werden.
2.1 Sterne vs. Planeten
Immer wieder vom Laien missverstanden werden die Ausdrücke „Planeten“ und „Sterne“
wild durcheinander geworfen, ohne sich des gravierenden Unterschiedes dieser im
Klaren zu sein.
Das beste und verständlichste Beispiel für einen Planeten wäre die Erde. Die Erde ist nur
einer von mehreren Planeten, die unser Zentralgestirn Sonne umkreisen. Für einen
Umlauf um die Sonne braucht die Erde ziemlich genau 365 Tage. Die anderen Planeten
des Sonnensystems, nämlich die „inneren“ Planeten Merkur, Venus, (Erde) und Mars
sowie die „äußeren“ Planeten Jupiter, Saturn, Uranus und Neptun kreisen der Erde gleich
in konzentrischen aber leicht ellipsenförmigen Bahnen um die Sonne.
Die „inneren“ Planeten sind ähnlich der Erde Gesteinsplaneten, nur dass sie aufgrund
ihrer geringen (Merkur, Venus) oder hohen Entfernung (Mars) zur Sonne ein für
Menschen zu heißes bzw. kaltes Klima bieten.
Die „äußeren“ Planeten sind allesamt Gasplaneten, d.h. sie besitzen keine wirklich feste
Oberfläche sondern bestehen aus Zusammensetzungen verschiedener Gase. Zwischen
den inneren und äußeren Planeten befindet sich im Sonnensystem eine Zone mit
tausenden kleiner, nur einige Kilometer Durchmesser messende Gesteinsbrocken,
welche als Planetoiden bezeichnet werden.
Alle diese Planeten umkreisen die Sonne in konstanten Abständen. Merkur als
sonnennächster Planet ist 58 Mio. km von der Sonne entfernt, Neptun als
sonnenfernster1 Planet 4498 Mio. km. Wir können mit einem guten Fernrohr die Planeten
unseres Sonnesystems betrachten. Das von ihnen ausgehende Licht ist das Sonnenlicht,
welches von diesen reflektiert wird.
1
Pluto gilt nur noch bei Sentimentalisten und Historikern als Planet unseres Sonnensystems.
Aufgrund seiner extremem Bahnabweichungen zur Ekliptik und der Tatsache, dass er zeitweise der
Sonne näher ist als Neptun, dann wieder ferner, wird er mittlerweile von vielen Astronomen nur noch
als großes Objekt des Kuiper-Gürtels angesehen.
5
Das beste Beispiel für einen Stern wäre unsere Sonne. Es gibt im Universum unzählige
Gebilde, die unserer Sonne ähneln – Sterne. Viele der Sterne, welche wir bei Nacht
sehen sind der Sonne sehr ähnlich, einige sogar bedeutend größer und heller als unsere
Sonne. Nur die Tatsache, dass diese so unglaublich weit entfernt sind, lässt sie auf
Punktgröße am Nachthimmel schrumpfen.
Die Entfernungen zu den nächsten Sternen sind wie gesagt „unglaublich weit“, in Zahlen
zwar auszudrücken, jedoch nicht für den täglichen Gebrauch empfehlenswert. Deshalb
haben sich Astronomen die Distanzangabe Lichtjahr ausgedacht.
Ein Lichtjahr ist die Strecke, welche ein Lichtstrahl in der gegebenen Zeit von genau
einem Jahr zurücklegt, etwa 9.4 Billionen km. Im Vergleich dazu: ein Lichtstrahl von der
Sonne braucht bis zur Erde etwa 8 Minuten, bis zum Neptun 4.16 Stunden.
Die durchschnittliche Entfernung von Sternen in unserem Teil der Galaxis beträgt 4-5
Lichtjahre! Der nächste Stern zur Sonne ist Proxima Centauri, dieser liegt 4,2 Lichtjahre
von der Sonne entfernt. Sterne reflektieren nicht wie die Planeten das Licht unserer
Sonne. Da Sterne an sich „Sonnen“ sind, strahlen sie ihr eigenes Licht aus.
Die vorliegende Studienarbeit befasst sich ausschließlich mit Sternen, nicht mit den sie
umkreisenden Planetensystemen. Folglich werden keine Planeten, Monde oder
Asteroiden behandelt.
6
2.2 Die solare Nachbarschaft
In klaren, dunklen Nächten können wir ohne Einsatz eines Teleskops mit dem bloßen
Auge etwa 6000 Sterne sehen. Schon ein flüchtiger Blick an den Nachthimmel offenbart
folgende Merkmale: Die Verteilung der Sterne ist nicht gleichförmig, die Sterne haben
nicht alle die gleiche Helligkeit, und es gibt ein schwach leuchtendes, unregelmäßiges
Band, das den Himmel zweiteilt.
Das diffuse Lichtband, das sich über den ganzen Himmel erstreckt, ist die Milchstraße.
(Der Ausdruck Galaxis ist aus dem griechischen Wort für „Milch“ abgeleitet.) Mit Hilfe von
kleinen Fernrohren oder sogar schon mit Feldstechern kann das Band in eine Unzahl von
einzelnen Sternen aufgelöst werden. Sie sind Mitglieder einer großen Galaxis, die von
schätzungsweise 1011 gravitativ aneinander gebundenen Sternen gebildet wird. Die
meisten der mit dem bloßen Auge sichtbaren Sterne sind Mitglieder unserer Galaxis, der
Milchstraße. Sie sind nah genug, so dass wir sie mit dem Auge als Einzelsterne auflösen
können.
Unsere Galaxis hat einen geschätzten Durchmesser von 70.000 Lichtjahren.
Alle Sterne und Objekte in weniger als 20 Lichtjahren Entfernung zur Sonne liegen in
unmittelbarer Nachbarschaft unseres Sonnesystems. Die durchschnittliche Entfernung
zweier Sterne in solarer Nachbarschaft beträgt etwa 5 Lichtjahre.
Das Programm stellt alle Sterne in solarer Nachbarschaft zur Sonne dar. Hierbei ist zu
beachten, dass die meisten Sterne in solarer Nachbarschaft mit dem bloßen Auge
eigentlich nicht zu erkennen sind, da sie als relativ kühle, rote Zwergsterne nicht
genügend starkes Licht emittieren.
2.3 Sternörter und Koordinaten
Unter Sternörter versteht man in der Astronomie die Angabe eines Satzes von
Koordinaten von Gestirnen. Alle Sternörter beziehen sich auf eine astronomische
Epoche, den Zeitpunkt ihrer Messung. Der Zeitpunkt der Messung ist relevant, da auch
Sterne sich mit der Zeit bewegen, allerdings (im astronomischen Maßstab gesehen) so
langsam, dass es dem menschlichen Auge nicht auffällt. Da die Geschwindigkeiten nur
einige hundert Kilometer die Sekunde betragen fällt die Eigenbewegung nicht so sehr ins
Gewicht als dass sie im vorliegendem Programm Beachtung finden.
Meistens sind diese Sternörter zweidimensional – d.h. auf die übliche (gedachte)
Himmelskugel bezogen. Die Erde befindet sich im Zentrum dieses Koordinatensystems,
welches auch als äquatoriales System bezeichnet wird. Von der Erde aus betrachtet
erhält ein Stern seine Koordinaten durch die Angabe zweier Werte, der Rektaszension
(RA) und der Deklination (Delta).
Die Rektaszension ist die Entsprechung der geografischen Längenkreise auf der
(imaginären) Himmelskugel. Als Nullpunkt der Rektaszension dient dabei der
Frühlingspunkt. Die Rektaszension, die bei der Positionsangabe von Himmelsobjekten
verwendet wird, wird von Norden aus betrachtet im Gegenuhrzeigersinn gemessen. In
der Astronomie hat es sich durchgesetzt, die Rektaszension nicht in Grad, sondern in
Stunden anzugeben, wobei 24h = 360° gesetzt werden.
7
Die Deklination entspricht der Projektion der Breitenkreise der Erde auf die
Himmelskugel. Die Deklination gibt somit den Winkelabstand eines Objekts vom
Himmelsäquator an. Werte nördlich des Äquators sind positiv, Werte südlich davon
negativ. Die minimale Deklination beträgt somit –90°, die maximale Deklination +90°.
2.4 Entfernungsmessungen über große Distanzen
Um die Entfernung zu sonnennahen Sternen zu messen hat sich das Verfahren der
Parallaxenverschiebung in der Astronomie bewährt. In diesem recht einfachen
trigonometrischen Verfahren wird der Winkel θ gemessen unter den man einen Stern zu
einem festen Zeitpunkt betrachtet; diese Messung wird genau ein halbes Jahr später
wiederholt [siehe Zeichnung]. Dieses halbe Jahr später befindet sich die Erde an einer
Position 300 Mio. km von der ersten Messung entfernt. Anhand der gemessenen Winkel
zu dem Stern ergibt sich ein Dreieck mit extrem großer Seitenlänge. Die Höhe dieses
Dreiecks berechnet sich nach Pythagoras. Die jährliche Parallaxe ist der Winkel, unter
dem die große Halbachse der Erdbahn vom Stern aus erscheint. Beträgt die Parallaxe
eine Bogensekunde (1/3600 eines Grades) so entspricht das einer Entfernung von 3,26
Lichtjahren oder rund 31 Billionen Kilometern. Diese Entfernung wird auch als Parsec
(parallax arcsecond) bezeichnet. Die Parallaxe ist selbst bei nahen Sternen so klein,
dass man sie lange nicht messen konnte. Selbst beim sonnennächsten Stern Proxima
Centauri beträgt die Parallaxe nur 0,772 Bogensekunden. In den 1990ern gelangen mit
dem Astrometriesatelliten HIPPARCOS genaue Parallaxenmessungen für viele Sterne.
Basierend auf den von HIPPARCOS gemessenen Daten werden die Koordinaten der
Sterne dreidimensional durch das Programm dargestellt.
8
2.5 Spektralklassen
Dem menschlichen Auge erscheinen die meisten Sterne als weiße Pünktchen am
Nachthimmel; nur bei wenigen Sternen wie z.B. Beteigeuze im Sternbild Orion erkennt
der Betrachter deren Farbe. Spektroskopische Messungen ergeben jedoch, dass nicht
alle Sterne sonnenähnlich sind, sprich gelbliches Licht ausstrahlen. Die meisten Sterne in
solarer Nachbarschaft sind so genannte rote Zwergsterne, d.h. relativ kühle, kleine und
für das bloße Auge meist gar nicht mehr sichtbare Sterne, welche rotes Licht
ausstrahlen. Dann wiederum gibt es auch sehr heiße, blau leuchtende Sterne. Die
verschiedenen
Typen
werden
durch
ihre
Spektralklasse
klassifiziert.
Als Spektralklasse bezeichnet man das System der Harvard-Klassifikation nach der alle
Sterne nach ihrer Oberflächentemperatur und chemischen Zusammensetzung
eingruppiert werden. Es wurde von Edward Charles Pickering, dem Direktor des Harvard
College Observatory und seinen Mitarbeitern zwischen 1890 und 1901 erarbeitet.
Klasse
O
B
A
F
G
K
M
Farbe
Blau
Blau-weiß
Weiß
Weiß-gelb
Gelb
Orange
Rotorange
Temperatur [in K]
28.000 – 50.000
9.900 – 28.000
7.400 – 9.900
6.000 – 7.400
4.900 – 6.000
3.500 – 4.900
2.000 – 3.500
Beispielsterne
Mintaka
Rigel, Spica
Wega, Sirius
Prokyon, Canopus
Capella, Sonne
Arcturus, Aldebaran
Beteigeuze, Kapteyns Stern
Die Spektralkassen mit ihren 7 Grundtypen (O,B,A,F,G,K,M) machen rund 99% aller
Sterne aus, weshalb die anderen Klassen oft vernachlässigt werden. Diesem Beispiel
folgend existieren auch in vorliegendem Programm nur jene 7 Grundtypen, zusätzlich
aber noch eine achte Klasse (T) für braune Zwergsterne.
2.6 Binär- und Trinärsternsysteme
Oft bilden sich in Sternentstehungsprozessen gleich mehrere Sterne, die örtlich nah
zusammen stehen und gravitationell gebunden sind. Diese Sterne umkreisen einen
gemeinsamen Schwerpunkt und bilden Binärsternsysteme (für je zwei sich umkreisende
Sterne) oder Trinärsternsysteme (für drei sich umkreisende Sterne). Viele Mehrfachsternsysteme sind mit bloßem Auge nicht von einfachen Sternsystemen zu unterscheiden.
Handelt es sich bei einem System um ein Binär- bzw. Trinärsternsystem, so stellt das
Programm die jeweiligen Sterne versetzt zueinander dar und lässt sie umeinander
rotieren.
Binärsternsystem mit gemeinsamen Rotationspunkt
9
3. Billboards
Unter einem Billboard versteht man einfach gesprochen eine Grafik, die sich stets nach
dem Betrachter ausrichtet. Hierbei kann man dem Billboard zusätzlich eine
Rotationsachse mitgeben um die Ausrichtung einzuschränken.
3.1 Rotationsachsen
In folgender Szenerie sieht man einen Tannenbaum [Bild 1], dargestellt über ein
Billboard.
Bewegt sich der Betrachter horizontal um diesen herum [Bild 2], so verändert sich der
Tannenbaum scheinbar nicht, da sich das Billboard zu dem Betrachter hin ausrichtet.
Bild 1
Bild 2
Dies liegt daran, dass einem Billboard eine feste Rotationsachse mitgegeben ist. Die
Rotationsachse des Billboards ist in folgenden Bildern die y-Achse, welche es dem
Billboard weiterhin erlaubt in x/z-Ebene zu rotieren [Bild 4], nicht aber in der x/y- oder z/yEbene.
Bild 3
Bild 4
Allerdings beschränkt diese Rotationsachse nun die Rotation des Billboards wie gesagt
allein auf die x/z-Ebene. Der Billboard-Tannenbaum rotiert nur in der x/z-Ebene, weshalb
er von einem Betrachtungspunkt weiter oberhalb nur noch als flache, eindimensionale
Linie wahrgenommen wird.
Bild 5
10
Wird die Rotationsachse des Billboards jedoch nicht gesetzt – es wird also speziell der
Nullvektor als Rotationsachse genommen – so kommt dieser Effekt nicht zustande.
Bild 6
Der Tannenbaum dreht sich jetzt stets mit der Kamera mit [Bild 6]. Scheinbar „liegt“ der
Baum nun auf dem Boden. Sich nach der Kamera ausrichtende Billboards nennt man
„View-aligned-Billboards“ (VABB).
VABBs sind demnach sehr praktisch für Szenen, in denen Objekte vorkommen, die
keiner festen Ausrichtung bedürfen. Sterne bieten sich an für den Einsatz von VABB.
3.2 Darstellung der Sterne als VABB
Die Sterne des vorliegenden Programms benötigen keine feste Verankerung. Sie stehen
an einer fixen Position im Raum, müssen sich nach nichts ausrichten außer dem
Benutzer. Von allen Seiten betrachtet sollen sie gleich aussehen, weshalb ein Effekt wie
in Bild 5 zu sehen äußerst ungünstig wäre.
Sterne werden nicht als 3D-Objekte, sondern als View-aligned-Billboards (VABB)
dargestellt. Die Entscheidung zur Darstellung der Sterne mittels VABBs wurde nicht aus
Performance-Gründen getroffen – hierzu werden zu wenig Sterne in das Modell
übernommen um einen merklichen Geschwindigkeitsvorteil zu erlangen -, sondern ergab
sich aus der einfachen Begebenheit heraus, dass zum einen ein Stern von allen Seiten
gleich aussieht und zum anderen VABB bis zu diesem Zeitpunkt selten benutzt worden
sind und somit eine Herausforderung darstellten.
Astronomische Spitzfindigkeiten wie z.B. die Radialgeschwindigkeit der Sterne, welche
diese an den Polen abflachen, oder Gebiete mit Temperaturschwankungen auf der
Sternoberfläche, die unregelmäßige Flecken hervorrufen, werden in vorliegendem Modell
nicht beachtet.
11
3.3 Zwei Varianten zur Darstellung
Aufgrund der äußerst spärlichen OpenSG-Dokumentation gestaltete sich die Ausrichtung
der Billboards zum Benutzer bzw. zur Kamera hin als eine mittlere Odyssee, welche
letztendlich aber zu einem überaus simplen doch sehr zufrieden stellendem Ergebnis
kam.
Der erste im Ergebnis suboptimale Ansatz basierte auf der Annahme, dass jedem
Billboard eine Rotationsachse mitgegeben werden muss. Somit ließ sich dass Problem,
dass sich das Billboard aus bestimmten Positionen betrachtet nur als schmale Linie
darstellt, auf 2 verschiedene Arten umgehen.
3.3.1 Variante 1
Variante 1 stellt die Sterne dar über den Einsatz zweier zueinander um 90° gekippter
Billboards.
Sterne mittels zweier gekippter Billboards darzustellen ist technisch gesehen sehr
einfach, liefert jedoch kein wirklich zufrieden stellendes Ergebnis, da dem ungeübten
Auge schnell die eigentliche Täuschung auffällt:
2 um 90° zueinander
gekippte Billboards
Man beachte das ringförmige Halo um den Stern sowie die 3D-Kugel, welche zusätzlich
als Geometrie an die Position des Sterns gesetzt worden ist. Das Halo ist zweimal
sichtbar, da es von beiden Billboards benutzt wird und diese um 90° zueinander gekippt
sind. Die Kugel ist nicht vollständig abgebildet, man sieht, dass sie von dem
waagerechten Billboard zerschnitten wird.
12
3.3.2 Variante 2
Variante 2 stellt die Sterne dar über eine dynamische Berechnung der Rotationsachse
zur Laufzeit
Die zweite Möglichkeit ist, den Stern nur durch ein einziges Billboard darzustellen. Die
Rotationsachse des Billboards muss aber stets im Winkel von 90° zu dem Vektor stehen,
der die direkte Verbindungslinie des Sterns und der Kamera beschreibt. Die Achse zur
Laufzeit dynamisch zu berechnen ist umständlich und soll nicht weiter vertieft werden, da
die im folgenden beschriebene Lösung des Problems weitaus einfacher ist.
Billboard mit dynamischer
Rotationsachse
Letztendlich führte ein Programmierfehler in zweitem Lösungsansatz zu der eigentlichen
Erkenntnis, dass eine Rotationsachse in vorliegendem Fall unnötig ist. Durch
umständliche Berechnungen hatte es sich ergeben, dass die Rotationsachse stets der
Nullvektor war. Somit ist es möglich, ein Billboard nach der Kamera auszurichten, indem
man einfach seine Rotationsachse gleich dem Nullvektor setzt und auf alle anderen
Berechnungen verzichtet.
13
4. Beschreibung des Programms
Im folgenden Kapitel wird beschrieben, wie Daten für die Erstellung der Sterne
eingelesen und verwaltet werden, wie mittels OpenSG der Szenengraph aufgebaut und
ein eigenes Navigationsmodell eingesetzt wird. Zu guter letzt werden zusätzliche
Features des Programms beschrieben.
4.1 Daten
Um die Sterne unserer solaren Nachbarschaft darzustellen benötigt man zu aller erst die
korrekten astronomischen Koordinaten dieser. Die HIPPARCOS-Mission der 90er-Jahre
führte zu einem umfassenden Katalog sehr präziser Sternörter der umliegenden
Gestirne. Die für das Programm relevanten Daten wurden in einzelne Textdateien
geschrieben, wobei jede Textdatei für einen Stern steht. Dies erlaubt dem User eine
einfache und unkomplizierte Bearbeitung der Daten. Die Textdateien sind im Verzeichnis
/stardata abgelegt.
Der Aufbau einer Textdatei ist im folgenden Beispiel beschrieben:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
Sirius
-1.612 -2.474 8.078
6.0 45.0 8.871
-16.0 42.0 57.99
8.601
2.03 0.02 0
2.35 0.98 0
B A 0
Sirius ist ein blaues Doppelsternsystem. Obwohl
SiriusB, der kleine Begleiter von SiriusA, nur
etwa ein hundertstel dessen Durchmesser misst,
fasst er dennoch ein Drittel der Gesamtmasse des
Systems.
Sirius A und B umkreisen einen gemeinsamen
Schwerpunkt.
Name des Systems
Kartesische Koordinaten
Rektaszension
Deklination
Entfernung zu Sol
Durchmesser (Sol=1)
Masse (Sol=1)
Spektralklasse
Zusätzliche textuelle Informationen
Hinweis: Beim Auslesen der Textdatei (s. 4.3) wird die erste Zeile komplett als Name
des Sterns ausgelesen. Es ist also darauf zu achten, die kartesischen Koordinaten sowie
anderen Daten unbedingt in nachfolgende Zeilen zu schreiben.
14
4.2 Die Klasse Star
Die Klasse Star verwaltet Objekte, die einen Stern bzw. Binär- oder Trinärstern
beschreiben. Ein Stern setzt sich aus folgenden relevanten Daten zusammen:
Name des Systems [string]
Kartesische Koordinaten
X [double]
Y [double]
Z [double]
Astronomische Koordinaten
Rektaszension
RA [double]
RAhour [double]
Ramin [double]
RAsec [double]
Astronomische Eigenschaften
Größe
Size [double]
SizeBi [double]
SizeTri [double]
Spektralklasse [char]
Deklination
DEC [double]
DECgrad [double]
DECmin [double]
DECsec [double]
Masse
Mass [double]
MassBi [double]
MassTri [double]
Textuelle Informationen [string]
Star-Objekte werden dazu benutzt, die aus den Textdateien stammenden Sterndaten zu
verwalten.
An Methoden bietet die Klasse Star nur gewöhnliche Getter&Setter, lediglich die
Methoden Star::calcXYZ() sowie Star::getInfo() führen Operationen aus.
Star::calcXYZ() berechnet aus einem Satz gegebener astronomischer Koordinaten
die korrekten kartesischen Koordinaten (s. 4.2.1), nach denen ein Stern vom Programm
positioniert wird; Star::getInfo() liefert einen string zurück, welcher die textuellen
Informationen in einer für die Anzeige formatierten Form enthält.
4.2.1 Umrechnung in kartesische Koordinaten
Die Umrechnung der astronomischen Koordinaten in kartesische Koordinaten erfolgt
mittels folgender Umrechnungsformel:
(
) ( )
dist * cosDEC * cosRA
=
dist * cosDEC * sinRA
dist * sinRA
x
y
z
Hinweis: Unter OpenSG ist die Y-Achse mit der Z-Achse vertauscht!
Hierzu müssen vorerst aber die in Winkelstunden, Winkelminuten und Winkelsekunden
vorliegenden astronomischen Koordinaten ins Gradmaß umgerechnet werden.
Es entsprechen:
Winkelstunde
Winkelminute
Winkelsekunde
=
=
=
15
15°
0.25°
0.00416°
4.3 Die Klasse Parser
Über die Klasse Parser erfolgt das Einlesen der benötigten txt-Dateien. Relevant ist hier
die Methode Parser::searchDirectory(), welche alle im Verzeichnis /stardata
befindendlichen txt-Dateien öffnet, deren Inhalt in Star-Objekten speichert und diese
Star-Objekte wiederum in einem Vektor ablegt.
Parser::searchDirectory() wird in stars-main.cpp innerhalb der Methode
createScenegraph() aufgerufen und liefert den benötigten Vektor mit allen
darzustellenden
Star-Objekten.
Im
folgenden
wird
beschrieben,
wie
Parser::searchDirectory() die in dem Verzeichnis /stardata liegenden txtDateien öffnet und ihren Inhalt in Star-Objekten speichert.
01 vector<Star>* Parser::searchDirectory(){
02
vector<Star>* stars = new vector<Star>; // Pointer to Vector
03
// storing our star-objects
04
struct _finddata_t c_file;
05
long hFile;
06
07
if( (hFile = _findfirst( "stardata/*.txt", &c_file )) == -1L )
08
cerr << "No *.txt files in current directory" << endl;
09
else {
10
cout << "Searching directory /stardata/..." << endl;
11
do {
12
Star aktuell;
// object star
13
ifstream datei;
// input filestream
Zuerst wird der Vektor stars angelegt, welcher später alle Star-Objekte enthalten soll
[Zeile 02]. Dann folgt ein Test, ob das angegebene Verzeichnis überhaupt gesuchte
Dateien enthält. Ist das Verzeichnis leer oder enthält keine txt-Dateien, so wird eine
Fehlermeldung ausgeworfen, andernfalls ein temporäres star-Objekt aktuell erzeugt und
ein input filestream für die erste zu lesende txt-Datei. Das ganze steht zudem in einer
do-while-Schleife [Zeile 11], damit jede txt-Datei ausgelesen wird. Zu beachten ist
außerdem, dass in Zeile 07 stets _findfirst( "stardata/*.txt", &c_file )
ausgeführt wird, also schon hier die erste gefundene .txt-Datei in dem Strukt c_file
abgelegt wird.
Folgende temporären Variablen speichern die ausgelesenen Informationen, bevor diese
an das Star-Objekt aktuell überschrieben werden.
14
15
16
17
18
19
20
21
22
string starname, textInfo, textInfoLine;//
unsigned char colorCode, colorCodeBi,
//
colorCodeTri;
//
double x, y, z,
//
size, sizeBi, sizeTri,
mass, massBi, massTri,
RAh, RAmin, RAsec,
DECgrad, DECmin, DECsec,
distance;
temporary variables
storing all the
stuff relevant to
object star
Jetzt wird die erste txt-Datei in einem input filestream geöffnet und ausgelesen. Zu
beachten ist, dass das Strukt c_file allerdings nur den einfachen Dateinamen, nicht aber
das eigentliche Verzeichnis in dem die Datei liegt speichert. Deshalb ist es nötig, zuerst
das Verzeichnis als Präfix im eigentlichen Dateinamen anzugeben.
16
23
24
25
26
27
string filename( "stardata/" );
filename += string( c_file.name );
datei.open(filename.c_str());
if (!datei) cerr << "mayday!";
else cout << c_file.name << " opened" << endl;
Nun beginnt das eigentliche Auslesen der Informationen. Da die erste Information in
jeder Textdatei der Name des Sternensystems ist, dieser jedoch auch Leerzeichen
enthalten kann (z.B. das Sternensystem „DX Cancri“), erfolgt hier das Auslesen mittels
der Methode getline.
28
29
30
getline(datei, starname); // here getline, so we can use
//starnames with whitespaces
aktuell.setName(starname);
Die folgenden Daten werden wie folgt ausgelesen:
28
29
30
31
32
33
34
35
datei >> x >> y >> z;
aktuell.setXYZ(x,y,z);
datei >> RAh >> RAmin >> RAsec >> DECgrad
>> DECmin >> DECsec >> distance;
aktuell.setRA(RAh,RAmin,RAsec);
aktuell.setDEC(DECgrad,DECmin,DECsec);
aktuell.setDistance(distance);
aktuell.calcXYZ();
Zeile 35 berechnet die kartesischen Koordinaten des Sterns neu, sollte die Distanz zur
Sonne nicht 0 Lichtjahre betragen. Die Abfrage hierzu erfolgt in der Methode
Star::calcXYZ().
Die letzten Informationen der Textdatei - die textuellen Informationen, welche später bei
der Selektion des Sterns angezeigt werden sollen - werden aus Gründen der
Performance wieder mittels getline ausgeslesen.
Zuletzt wird die aktuelle Datei geschlossen [Zeile 36], das mit Daten gefüllte Star-Objekt
in den Vektor stars verschoben [Zeile 39] und auf die nächste txt-Datei zugegriffen
[Zeile 42].
36
datei.close();
// close txt-file
37
cout << c_file.name << " closed" << endl;
38
39
stars->push_back(aktuell); // push starObject into vector
40
cout<<endl; cout<<endl;
41
}
42
while (_findnext(hFile, &c_file)==0);
43
}
44
return stars;
45 }// END searchDirectory
Die Methode beendet ihre Aktivitäten mit Rückgabe des Vektors stars [Zeile 44].
17
4.4 Aufbau des Szenegraphen
Der Szenegraph des Programms präsentiert sich wie folgt:
An die Stelle „ STAR-SYSTEM “ werden die verschiedenen Sterne bzw. Sternensysteme
gehangen, eine genauere Erläuterung hierzu folgt in 4.4.1 und 4.4.2.
18
4.4.1 Die Methode createStar
Im folgenden wird beschrieben, wie ein Billboard-Stern unter OpenSG modelliert wird.
Die Methode NodePtr createStar(NodePtr BillboardNode, string name,
double size, unsigned char colorCode) in stars-main.cpp erzeugt die
für den Stern notwendige Geometrie, belegt diese mit einer Textur und hängt sie unter
einen im ersten Argument angegebenen Billboard-Knoten.
Zuallererst wird ein Knoten benötigt, der die Geometrie beinhalten soll, welche das
darzustellende Bild als Textur besitzt. Für die Geometrie empfiehlt sich eine Ebene.
01 GeometryPtr planegeo = makePlaneGeo(size,size,1,1); // 1st geometry-core
Im Core planegeo befindet sich nun die Beschreibung für eine Ebene mit den Ausmaßen
size x size. Size ist für jeden Stern unterschiedlich, je nachdem wie groß er ist. Da die
Ebene bis jetzt aber noch keine Textur hat, wird die Ebene mit einer Textur belegt die
beim Start des Programms bereits global kreiert worden ist.
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
beginEditCP(planegeo, Geometry::MaterialFieldMask);
switch(colorCode){
case ‘O’:
{planegeo->setMaterial(blue);}
break;
case ‘B’:
{planegeo->setMaterial(bluewhite);} break;
case ‘A’:
{planegeo->setMaterial(white);}
break;
case ‘F’:
{planegeo->setMaterial(yellowwhite);}break;
case ‘G’:
{planegeo->setMaterial(yellow);}
break;
case ‘K’:
{planegeo->setMaterial(orange);}
break;
case ‘M’:
{planegeo->setMaterial(red);}
break;
case ‘T’:
{planegeo->setMaterial(brown);}
break;
case ‘E’:
{planegeo->setMaterial(sol);}
break;
case ‘R’:
{planegeo->setMaterial(redflare);}
break;
case ‘S’:
{planegeo->setMaterial(bab5);}
break;
default:
{planegeo->setMaterial(bab5);}
break;
}
endEditCP(planegeo, Geometry::MaterialFieldMask);
Da für die Sterne je nach Spektralklasse verschiedene Texturen benötigt werden, erfolgt
deren Zuweisung in einer switch-Anweisung über ihren Farbcode. Nun befindet sich im
Core planegeo die Beschreibung einer Ebene mit den Ausmaßen size x size und einer
Texturierung. Jetzt muss planegeo an einen Knoten gehangen werden.
18
19
20
21
22
23
NodePtr geometryNODE = Node::create();
beginEditCP(geometryNODE, Node::CoreFieldMask);
geometryNODE ->setCore(planegeo);
endEditCP(geometryNODE, Node::CoreFieldMask);
// ... give a name to the node, so we can easily find it later on...
setName(geometryNODE, name);
Der Knoten geometryBillboard stellt jetzt im Programm eine fest im Raum stehende
texturierte Fläche dar. Bei einer Rotation um diese dreht sie sich natürlich noch nicht mit
der Kamera mit, da sie kein Billboard ist. Dies wird dahingehend verändert, indem über
den geometryBillboard-Knoten einen Billboard-Knoten gehangen wird.
Hinweis: Es ist wichtig, der Geometrie des Billboards einen Namen mitzugeben. Später
wird anhand dieses Namens auf den Vektor mit den Star-Objekten zugegriffen werden
müssen.
19
Aber das wichtige zuerst: der Core für den Billboard-Knoten.
24
25
26
27
28
29
30
// ... above the geometryBillboard-Nodes shall be BillboardNodes,
// so the geometry becomes a flattened image always facing the camera
beginEditCP(billyBoy);
// core already created in createSceneGraph()
billyBoy->setAlignToScreen(true);
billyBoy->setAxisOfRotation(Vec3f(0,0,0));
billyBoy->setFocusOnCamera(false);
endEditCP(billyBoy);
//Billboards now face the camera
Der Core billyBoy wird, wie in Zeile 26 beschrieben, bereits in NodePtr
createSceneGraph(void) erstellt:
billyBoy = Billboard::create();// create core for star-billboards
Somit teilen sich alle im folgenden erstellten Billboard-Knoten für die Sterne ein und
denselben Core billyBoy.
Wichtig ist nun, dass dem Core keine Rotationsachse mitgegeben wird [Zeile 28]. Nur der
Einsatz des Nullvektors bewirkt, dass sich das zukünftige Billboard von jeder
Kameraposition aus zum Bildschirm hin ausrichtet (s. 3.1). Eine Rotationsachse
beschränkt hier die Ausrichtung des Billboards! Standardmäßig sind die Methode
setAlignToScreen [Zeile27] und setFocusOnCamera [Zeile 29] auf true gesetzt. Die
erste Methode bewirkt, dass sich die Billboards zum Bildschirm hin ausrichten. Die zweite
Methode lässt die Billboards auf die Kamera ausrichten, d.h. sie stehen orthogonal zu
dem Vektor zwischen Kamera und ihrer eigenen Position. Dies führt gerade in den
Fällen, in denen die Sterne an den Rand des Bildschirms dargestellt werden zu einem
unrealistischem Erscheinungsbild, wie folgende Bilder zeigen:
Bild 1
Bild2
Beide Bilder zeigen die untere rechte Ecke des Fensters, in dem das Programm läuft.
Der Billboard-Knoten von Bild 1 hat die Methode setFocusOnCamera mit dem
Parameter true aufgerufen, der Billboard-Knoten von Bild 2 mit false. In der Endversion
des Programms werden alle Billboards nur auf den Bildschirm, nicht aber auf die Kamera
ausgerichtet, somit ergibt sich das gewünschte Bild [Bild2]. Anzumerken sei außerdem,
dass sich auf die Kamera fokussierte Billboards [Bild 1] nicht weiter zu dieser hin
ausrichten, sollten sie einer Rotation unterworfen werden (sprich der Billboard-Knoten
hängt unter einem Rotationsknoten).
20
Aber bevor obige Bilder zu sehen sind, muss natürlich erst der Core an einen Knoten
gehangen und dieser über den GeometryNODE-Knoten gesetzt werden.
31 beginEditCP(BillboardNode, Node::CoreFieldMask|Node::ChildrenFieldMask);
32
BillboardNode->setCore(billyBoy);// set the core of BillboardNode
33
BillboardNode->addChild(geometryNODE);
34 endEditCP(BillboardNode, Node::CoreFieldMask|Node::ChildrenFieldMask);
35 return BillboardNode;}
Im Szenegraphen zeigt sich der zum Billboard gewandelte Stern wie folgt:
4.4.2 Die Methode createSystem
Ein Sternensystem kann aus bis zu 3 Sternen bestehen. Diese Sterne umkreisen einen
gemeinsamen Schwerpunkt.
Der Schwerpunkt dieses Systems liegt auf den eigentlichen Koordinaten des
Sternensystems. Die ihn umkreisenden Sterne rotieren um den Schwerpunkt in geringer
Entfernung.
Es gibt nun folgende drei Fälle:
a) Singulärsystem
Es wird genau einmal die Methode createStar aufgerufen. Der hieraus
resultierende Teilszenegraph wird in den Gesamtszenegraphen eingefügt, wobei
ein Knoten zwischen die beiden Szenegraphen geschaltet wird der die Translation
des Sterns zu seinen Koordinaten fasst.
21
b) Binärsystem
Es werden zwei Singulärsysteme in dichtem Abstand zueinander erzeugt – der
Abstand der beiden Sterne zueinander wird über jeweils einen Translationsknoten
oberhalb des Singulärsystems gewährleistet. Jene Singulärsysteme werden unter
einen gemeinsamen Rotationsknoten gehangen und letztendlich wie in a) mit
einem dazwischengeschalteten Translationsknoten an den Gesamtszenegraphen
angefügt.
22
c) Trinärsystem
Es wird ein Binärsystem erzeugt, ein dritter Stern wird in geringen Abstand zu
jenem gesetzt (vgl. Erzeugung des Binärsystems). Das Binärsystem und das
Singulärsystem werden unter einen gemeinsamen Rotationsknoten gehangen
und wie in a) mit einem dazwischengeschalteten Rotationsknoten an den
Gesamtszenegraphen angefügt.
23
Der Quellcode der Methode createSystem soll hier nicht im genauen erläutert werden.
Dem aufmerksamen Auge fällt allerdings bei obigen drei Szenegraphen eine gewisse
Redundanz auf: Der Szenegraph für das Singulärsternsystem ist auch Teil der
Szenegraphen für Bi- bzw. Trinärsternsysteme, der Szenegraph für das
Binärsternsystem ist Teil des Szenegraphen für Trinärsternsysteme. Durch geschicktes
Erzeugen und Verbinden der verschiedenen Teilszenegraphen können hiermit im
Quellcode ein paar Zeilen eingespart werden.
Grob gesehen besteht createSystem aus zwei aufeinander folgenden switch/caseAnweisungen mit jeweils drei Fällen. Die erste switch/case-Anweisung erzeugt je
nachdem um welchen der obigen Fälle es sich handelt die benötigten Nodes und Cores,
die zweite switch/case-Anweisung setzt diese zu einem Teilszenegraphen zusammen.
24
4.4.3 Skalierung der Sterne
Eine Einheit im System beträgt ein Lichtjahr. Die Sterne werden deshalb nicht in
originalgetreuer Größe abgebildet, da sie sonst im Subpixelbereich lägen. Die Sonne
wird auf einer Ebene mit 1E Kantenlänge abgebildet – dies entspricht einem Lichtjahr –,
die restlichen Sterne skaliert dargestellt. Die Skalierung macht in dem Fall Sinn, da die
meisten Sterne in 20 LJ Entfernung zur Sonne weniger als 20% des
Sonnendruchmessers messen und somit kaum mehr sichtbar wären. Die Sterne, welche
größer als die Sonne sind, werden ein wenig kleiner dargestellt um die Aufmerksamkeit
des Benutzers nicht auf eine handvoll weniger, sehr großer Sterne zu fokussieren.
Es gilt für Sterne <Sol:
Darstellung = 3/4 * Größe + ¼
Es gilt für Sterne >Sol:
Darstellung = ½ * Größe + ½
Die Skalierung der Sterne findet sich im Code innerhalb der Methode createSystem()
wieder.
25
4.5 Einfügen eines Sky-Backgrounds
Zu den Anfängen der Studienarbeit befand sich das Programm in folgendem Zustand:
Das Modell der Sterne ließ sich zwar schon von allen Seiten mittels Kamerarotation aus
betrachten, allerdings blieb der Hintergrund monoton schwarz. Nachdem ein
Hintergrundbild eingefügt wurde bekam der Betrachter der Szene sehr schnell das
Gefühl, sich nicht selbst mit der Kamera um die Sterne zu drehen sondern die Szene
bzw. die Sterne an sich zu drehen, da das Hintergrundbild fest verankert sich nicht mit
der Szene bewegte. Es wurde der Eindruck erweckt, dass nur einige Sterne der
Milchstraße (welche im Hintergrundbild dargestellt war) bewegt wurden; bei dieser
Bewegung wurden die Sterne aber offensichtlich aus der Milchstraße „herausgerissen“,
da sich diese im Hintergrund nicht mitbewegte.
Um das Gefühl des Betrachters, sich tatsächlich in einem dreidimensionalen Raum zu
befinden, zu erhöhen, empfiehlt sich der Einsatz eines SkyBackgrounds. Unter einem
SkyBackground versteht man eine Reihe von Texturen, welche auf einen Würfel, der die
gesamte Szene beinhaltet, gezeichnet werden. Die verschiedenen Seiten des Würfels
lassen sich durch Rotation der Kamera anschauen, nie aber kann sich der Betrachter
diesen nähern, sie befinden sich stets in einem konstanten Abstand zur Kamera.
Die Bilder, welche auf die verschiedenen Seiten des Würfels gemalt werden, sollten
natürlich an den benachbarten, zusammenstoßenden Kanten ähnliche Bildinformationen
beinhalten, um den nicht den Eindruck zu vermitteln, sich in gerade demselbigen Würfel
zu befinden. Es empfiehlt sich daher zuerst den kompletten Skybackground in einem Bild
zu malen und dieses nachher in Einzelbilder zu zerschneiden.
Skybox (4096x3072 Pixel)
Die Seiten des Skybackgrounds werden wie folgt mit Bildern belegt:
Zuerst benötigt man für jede der 6 Seiten des Würfels einen ImagePtr, welcher die
Bildinformationen enthält:
01 ImagePtr skyfront = Image::create();
Diesem ImagePtr muss nun ein Bild zugewiesen werden:
02 beginEditCP(skyfront);
03
skyfront->read("skybackground/sky-front.jpg");
04 endEditCP(skyfront);
Der Skybackground selbst benötigt allerdings sogenannte TextureChunks in denen die
ImagePtr ihre Bilder übergeben. Des weiteren sind TextureChunks dazu in der Lage die
26
6 Bilder des Würfels an ihren Kanten zu falten [Zeile 09], so dass eventuelle Artefakte
(siehe Bildvergleich) unterdrückt werden.
05
06
07
08
09
10
11
12
13
TextureChunkPtr FrontTexture = TextureChunk::create();
// then we store it in a TextureChunkPtr
beginEditCP(FrontTexture);
FrontTexture->setImage(skyfront);
FrontTexture->setWrapS(GL_CLAMP_TO_EDGE); // to avoid edges
FrontTexture-setMinFilter(GL_LINEAR_MIPMAP_LINEAR);
FrontTexture->setMagFilter(GL_LINEAR);
endEditCP(FrontTexture);
Der Einsatz eines Filters zur Faltung der Bilder an den Würfelkanten lohnt sich, wie
folgende Screenshots zeigen:
links: ohne Filter
rechts: mit Filter
Nun verfügt der TextureChunk “FrontTexture” über den ImagePtr „skyfront“ und somit
über das Bild „skybackground/sky-front.jpg“. Jetzt muss der TextureChunk nur noch
einem SkybackgroundPtr übergeben werden. Hierzu muss dieser erst einmal erzeugt
werden:
14 SkyBackgroundPtr skyBkg = SkyBackground::create();
Dann übergibt man in der gewohnten beginEditCP..endEditCP-Schreibweise den
TextureChunk:
15 beginEditCP(skyBkg);
16
skyBkg->setFrontTexture(FrontTexture);
17 endEditCP(skyBkg);
27
Diese Prozedur wiederholt sich 5 Mal für die restlichen Seiten des Skybackgrounds. Den
fertigen Skybackground muss man dann in der main-Funktion seinem Viewport zuweisen
[Zeile 05]:
01
02
03
04
05
06
07
08
SkyBackgroundPtr skyBkg = makeSky();
myViewport = Viewport::create();
beginEditCP(myViewport);
myViewport->setCamera(myCamera);
myViewport->setBackground(skyBkg);
myViewport->setRoot(scene);
myViewport->setSize(0,0,1,1);
endEditCP(myViewport);
4.6 Navigation
Als eine Herausforderung stellte sich das Einbinden einer eigenen Navigation dar mit
gleichzeitigem Verzicht auf den SimpleSceneManager von OpenSG.
Der SimpleSceneManager erlaubt dem Programmierer das einfach Einbinden
verschiedenster Navigationsmöglichkeiten wie den Fly-Navigator oder TrackballNavigator. Alle Variationen aber bringen ein schwerwiegendes Problem mit sich, dass im
folgenden erläutert werden soll.
4.6.1 Oben/Unten im Weltraum
Die Begriffe „oben“ und „unten“ sind im Weltraum ohne Bedeutung; aufgrund der
Schwerelosigkeit merkt beispielsweise ein Astronaut nicht, ob er sich kopfüber bewegt
oder in Schieflage befindet. Nur an der Ausrichtung bekannter Landmarken (wie zum
Beispiel einer Raumstation oder einem Planeten) kann sich der Astronaut orientieren. Ein
Programm, welches die Lage der Sterne zueinander darstellt ohne dabei aber im
weiteren auf bekannte Objekte und Landmarken wie der Erde einzugehen, beherbergt
nun eine ganze Fülle von Möglichkeiten, dem User die Orientierung zu rauben. Die
dargestellten Sterne sind gerade beim allerersten Betrachten einem Laien nicht sehr
vertraut. Vollführt der laienhafte User eine Bewegung um diese Sterne herum, so vermag
er vielleicht diese Bewegung zu ihrem Ursprung zurück zu führen, sprich sich wieder in
eine Lage in dem System zu versetzen, die er zu Beginn eingenommen hat – doch nach
einigen weiteren und teils komplizierten Bewegungen um das Sternenmodell wird er
seine Ursprungslage verloren haben.
Kommen für den User noch Drehungen um die eigene Achse hinzu, so stünde das ganze
Modell irgendwann auf dem Kopf – spätestens jetzt verliert der User seine Orientierung,
liefern doch einige bisher unbekannte Sterne keine konkreten Anhaltspunkte über den
eigentlichen Aufenthaltsort im Weltraum.
Navigationsmodelle wie der Fly-Navigator oder Trackball-Navigator besitzen gerade
diese Schwäche, dass sich der User „kopfüber“ durch das Modell bewegen kann.
28
Erste Abhilfe verschafft hier der Einsatz eines geeigneten Skybackgrounds, an dem sich
der User orientieren kann.
Das im folgenden beschriebene Navigationssystem umgeht dies und bietet dem User
eine intuitivere Navigation welche ihm zusätzlich nicht die Orientierung raubt sondern
vielmehr ein Gefühl für „oben“ und „unten“ im Weltall gibt. Das System gleicht dem
polarem System der Bestimmung von Sternörtern (s. 2.4) und wird im folgenden als
„Polar-Navigator“ (PN) umschrieben.
4.6.2 Einbinden einer eigenen Navigation
Die Kamera navigiert im PN um einen fixen Punkt. Dabei rotiert sie um diesen Punkt in
zwei Richtungen, der Horizontalen sowie Vertikalen. Für die horizontale Rotation dreht
sich die Kamera um die y-Achse, für die vertikale Rotation um eine zur y-Achse
orthogonal verlaufende Achse, die x-Achse. Die Rotation um die Horizontale ist ohne
Einschränkungen, jedoch ist die Rotation um Vertikale auf 180° beschränkt. Dies bewirkt,
dass sich die Kamera zwar um ein Objekt in horizontaler Ebene herumbewegen, dieses
zusätzlich auch von oben oder unten betrachten kann, sich aber niemals bei einer
Kamerabewegung über das Objekt hinüber „überschlägt“.
Rotationen des PN
Sämtliche Rotationen werden im Core myCamRotation der Node naviTransNode
vollzogen, der Zoom findet im perspectiveCameraPtr myCamera innerhalb der Node
myCamBeacon statt (s. 4.4).
29
Folgende Variablen sind in stars-main.cpp global definiert:
01
02
03
04
05
06
07
float
oldX, oldY, zoom = 8,
// variables for mouse movement...
angleRA, angleDE; // ... and the angle of camera
Quaternion qRA, qDE;
// rotation Quaternions
Matrix
camM,
// camVec (starting[0 0 8]) for zoom in camM[3]
starRotation;
// Matrix for the rotation of binary stars
Vec3f
xAxis
= Vec3f(1,0,0),
// x-axis
yAxis
= Vec3f(0,1,0);
// y-axis
Die Variablen oldX und oldY sind Hilfsvariablen um die Bewegung der Maus abzufangen.
angleRA ist der Winkel für die Rotation in der horizontalen Ebene – hierfür wird auch das
Quaternion qRA benötigt -, angleDE und qDE werden benötigt für die Rotation in
vertikaler Ebene.
Innerhalb der Methode void motion(int x, int y) wird nun der Polar-Navigator
zum Leben erweckt:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
float dX = x - oldX;
float dY = y - oldY;
if (motionState == ROTATE){ // RIGHT_BUTTON is pressed
Matrix naviMat = myCamRotation->getMatrix();
angleDE -= 0.5 * dY;
// must stand before DE-locking
angleRA += 0.5 * dX;
// must stand before DE-locking
// _DECLINATION LOCK_ [important for orientation in 3D]
if (angleDE >= 90){
// locks DE to +90 degrees
angleDE=90;
// camera stays straight above sun
}
else if (angleDE <= -90){ // locks DE to -90 degrees
angleDE=-90;
// now camera stays right below sun
}
Zuerst wird in dX und dY gespeichert, wie sehr der User die Maus in x- bzw. y-Richtung
bewegt hat [Zeile 1+2]. Bei gedrückter rechter Maustaste ist motionState auf ROTATE
gesetzt (dies geschieht innerhalb der Funktion void mouse(int button, int
state, int x, int y)).
In der Matrix naviMat wird nun der Zustand der Kamera gespeichert [Zeile 5]. Hierzu wird
aus dem Core myCamRotation mittels getMatrix() die aktuelle Matrix, welche die
Kameraposition enthält, geholt.
Nachdem die Bewegung der Maus auf die Rotationswinkel addiert wurde [Zeile 6+7] folgt
ein clamping für angleDE um das oben beschriebene „Überschlagen“ der Kamera um
den Rotationspunkt zu vermeiden.
15
16
17
18
19
20
21
22
23
qRA.setValueAsAxisDeg(yAxis, angleRA );
qDE.setValueAsAxisDeg(xAxis, angleDE);
qRA.mult(qDE);
naviMat.setRotate(qRA);
beginEditCP(myCamRotation, Transform::MatrixFieldMask);
myCamRotation->setMatrix(naviMat);
endEditCP(myCamRotation, Transform::MatrixFieldMask);
30
Jetzt kommen die Quaternionen zum Einsatz! In Zeile 15 wird die Drehung in der
horizontalen Ebene in das Quaternion qRA eingerechnet, in Zeile 16 die Drehung in der
vertikalen Ebene in das Quaternion qDE.
Die beiden Quaternionen müssen jetzt noch miteinander multipliziert werden [Zeile 18],
das Ergebnis dieser Multiplikation wird in qRA gespeichert, welches dann in Zeile 19 in
die Matrix naviMat eingeht, die die Position der Kamera speichert.
Zu guter letzt muss naviMat noch zurück in den Core myCamRotation eingefügt werden
[Zeile 22].
Bis jetzt ist es also möglich, die Kamera um einen Stern zu rotieren, es fehlt noch der
Zoom auf diesen. Auch dieser befindet sich in void motion(int x, int y)
24
25
26
27
28
29
30
31
32
33
34
if (motionState == ZOOM){
zoom += 0.1* dY;
if (zoom<=1) zoom = 1;
else if (zoom>=45) zoom = 45;
beginEditCP(myCamTrans);
camM.setTransform(Vec3f(0,0,zoom));
myCamTrans->setMatrix(camM);
endEditCP(myCamTrans);
}
Bei gedrückter mittlerer Maustaste [Zeile 24] wird nun der Zoomfaktor mit der Bewegung
der Maus in vertikaler Richtung aufaddiert und geclampt [Zeile 26-28]. Der minimale
Zoom beträgt 1 Lichtjahr, der maximale 45 Lichtjahre.
Der für den Zoom verantwortliche Core befindet sich nicht in myCamRotation sondern in
myCamTrans, dem Core von myCamBeacon.
31
4.7 Picking
Dem Benutzer soll es möglich sein, Sterne per Mausklick zu selektieren. Hierbei soll der
selektierte Stern hervorgehoben und zusätzlich Information zum Stern eingeblendet
werden.
Im folgenden Abschnitt wird erklärt werden, wie das Picking, d.h. der Vorgang, mit dem
der User einen Stern selektiert, im Programm umgesetzt worden ist. Das Hervorheben
des Sterns wird genauer in 4.9.3 erklärt; die Einblendung von Informationen in 4.8.
Die Methode void singleClick(int x,int y) prüft, ob bei einem Linksklick ein
Stern angeklickt worden ist:
01
02
03
04
05
06
07
08
09
Line l;
myCamera->calcViewRay(l,x,y,*myViewport);
IntersectAction *act = IntersectAction::create();
act->setLine(l);
act->apply(myLightNode);
// did we hit something?
if (act->didHit())// yes!!
{
. . .
Zuerst wird eine Gerade erzeugt, anhand derer auf einen Schnitt mit der vorhandenen
Geometrie geprüft wird [Zeile 01]. Hierzu wird die von OpenSG mitgelieferte Methode
calcViewRay(...) angewendet. Jene Methode benötigt die aktuellen Koordinaten des
Mauszeigers über dem Fenster (hier x und y) sowie den zugehörigen Viewport. Mittels
der Mauskoordinaten und dem Viewport berechnet calcViewRay() nun diejenige Gerade,
welche von der virtuellen Kamera aus den Punkt des Bildschirms bei den
Mauskoordinaten durchstößt und weiter in die Szenerie hineinragt. Die Ergebnisgerade
wird in der in Zeile 1 erzeugten Geraden gespeichert.
Nun wird eine IntersectAction erstellt [Zeile 03]. Diese IntersectAction benötigt die eben
erzeugte Schnittgerade [Zeile 04] und testet, ob jene Gerade eine im Szenegraph
vorhandene Geometrie schneidet. Hierbei ist es aber unnötig, den Szenegraph von der
Wurzel aus auf einen Schnitt zu testen, deswegen reicht ein Test ab dem Knoten
myLightNode vollkommen [Zeile 05].
Jetzt wird nur noch geprüft, ob das getroffene Objekt – was hier nur die Geometrie eines
Billboards sein kann – einen Namen hat (vgl. die Methode createStar).
Da die einzig vergebenen Namen diejenigen sind, welche auch die Star-Objekte
innehaben, kann man nun den Vektor stars (vgl. 4.3) nach dem star-Objekt durchsuchen,
welches die Informationen des angeklickten Sterns enthält.
32
4.8 Einblenden von Informationen
Bei Selektion eines Sterns werden die zu dem Stern gehörigen Informationen auf dem
Bildschirm präsentiert. Da OpenSG nicht über ausreichende Mittel verfügt Text schnell
und unkompliziert darzustellen, muss hier ein kleiner Umweg gegangen werden.
Im folgenden wird das grobe Vorgehen beschrieben:
Klickt der User auf einen Stern, so wird in dem zugehörigen Star-Objekt die textuelle
Information ausgelesen. Dann wird für jeden einzelnen ausgelesenen Buchstaben eine
separate Ebene erzeugt, auf die die Textur dieses Buchstabens gelegt wird. Somit ist es
möglich, durch aneinanderhängen verschieden texturierter Ebenen den kompletten Text
darzustellen.
Alle diese Ebenen werden unter einem Teilszenegraphen zusammengefasst, welcher
dann in geringer Distanz direkt vor die Kamera gestellt, bzw. unter den Kameraknoten
gehangen wird. Somit bleibt der Text stets im Sichtfeld des Users auf dem Bildschirm.
Zu beachten ist hier nur noch die Formatierung des Textes, d.h. ab wann im Programm
z.B. ein Zeilenumbruch stattfindet. Dies soll verhindern, dass sehr große Texte in
Bereiche geschrieben werden, die von der Kamera her nicht mehr einsehbar sind;
umgangssprachlich formuliert könnte man sagen, dass der Text nicht aus dem Bildschirm
„herauswandert“. Ein manueller Zeilenumbruch ist innerhalb der Textdateien schon
mittels des Sonderzeichens „ | “ zu setzen.
Die Methode Star::getInfo() bringt die textuellen Informationen derart in Form, dass
sie vor den eigentlichen anzuzeigenden Text die Basisinformationen zum angeklickten
Stern setzt, beispielsweise den Namen des Sterns, seine Koordinaten, Größe, Masse
etc..
Star::getInfo() erzeugt noch nicht den Teilszenegraphen welcher dann letztendlich
vor die Kamera gehangen werden muss. Hierfür sorgt die Klasse Info mit der Methode
Info::renderInfo(...).
InfoGroupNODE wird mit dem unter ihr liegendem Teilszenegraphen von der Methode
zurückgegeben und später dann unter den Kameraknoten gehangen. TexTransNODE
hält die Transformationen für die einzelnen Ebenen, sprich die Positionen, an denen die
Buchstaben auf dem Bildschirm erscheinen sollen. TexGeoNODE enthält die eigentliche
Ebene, auf der als Textur der darzustellende Buchstabe gezeichnet ist.
33
Informationseinblendung
34
4.9 Diverse Effekte
In den folgenden Abschnitten werden kleinere Effekte beschrieben, die sozusagen als
Feinschliff dem Programm mehr Dynamik geben.
4.9.1 FTL-Effekt
Unter FTL versteht man den in englischsprachiger Science-Fiction geprägten Ausdruck
von Reisen mit Überlichtgeschwindigkeit (Faster Than Light).
Beim Zoom auf einen Stern wird die Lichtgeschwindigkeit vom Betrachter drastisch
überschritten, da in der Regel kein User sich die Zeit nimmt, für 1E im Modell ein ganzes
Jahr lang – ohne Unterbrechung – zu zoomen. Um die Geschwindigkeit zu verdeutlichen
verzerrt sich bei einer vorwärts-rückwärts Bewegung der Kamera das Bild.
Realisiert wird dies durch das „Field of View“ (FOV) der Kamera, welches den
überschaubaren Bereich derselben angibt. Standardmäßig ist das Field of View auf 60°
gesetzt, d.h. der Betrachter überblickt in einem Winkel von 60° die Szene.
Bewegt sich nun der Betrachter mit Überlichtgeschwindigkeit nach vorne, so „überholt“ er
quasi Lichtstrahlen, die von hinter ihm liegenden Gegenständen an ihm vorbeistrahlen.
Dieses Licht sieht er, womit sich sein Blickwinkel dermaßen erhöht, dass er diese hinter
ihm liegenden Gegenstände sehen kann. Das FOV wird auf einen Wert >60° gesetzt und
der Blickwinkel offenbart dem Betrachter nun Gegenstände, die sich seitlich hinter ihm
befinden.
Umgesetzt
wird
dies
void motion(int x, int y):
01
02
03
04
05
06
07
08
09
10
im
Code
innerhalb
der
Funktion
// The following stuff is for the FTL-effect
if (dY<0){// if moving forward
fov+=2;// our field of view gets wider
if (fov>=145) fov =145;// until it is really wide
if (fov<=45) fov =45;
beginEditCP(myCamera);
myCamera->setFov(deg2rad(fov));// setting field of view
endEditCP(myCamera);
}
Bewegt sich der Betrachter mit Überlichtgeschwindigkeit nach hinten, so dürfte er
eigentlich nichts mehr sehen, da sämtliche auf seine Augen gerichteten Lichtstrahlen
„nur“ mit Lichtgeschwindigkeit diesen hinterherjagen, sie aber nicht berühren. Da ein
schwarzer Bildschirm allerdings die wenigsten User begeistert, wurde hierauf verzichtet
und statt dessen das FOV bei einer Rückwärtsbewegung auf einen Wert kleiner 60°
gesetzt:
35
11
12
13
14
15
16
17
18
19
if (dY>0){// if moving backward
fov-=0.1;// our field of view gets smaller
if (fov<= 45) fov = 45; // until it is really small...
if (fov>=145) fov = 145;
beginEditCP(myCamera);
myCamera->setFov(deg2rad(fov));// setting the field of view
endEditCP(myCamera);
}
Beendet der User den Zoom (loslassen der mittleren Maustaste), so fällt er wieder unter
die Lichtgeschwindigkeit. Das FOV wird zurück auf 60° gesetzt. Um einen allzu
deutlichen Sprung bei einem Abbremsen von der Lichtgeschwindigkeit zu vermeiden,
wird das FOV schrittweise auf 60° zurückgesetzt – dem Betrachter wird der Eindruck
vermittelt, dass er sacht abbremse. Umgesetzt wird dies im Code innerhalb der Funktion
void display(void):
01
02
03
04
05
06
07
08
09
if (waiting == 1){// FTL-Effect
if (fov>=63)fov-=3;
else if (fov<57) fov+=3;
else fov=60;
beginEditCP(myCamera);
myCamera->setFov(deg2rad(fov));
endEditCP(myCamera);
}
Jener Code muss in der display-Funktion stehen, da diese laufend vom Programm
aufgerufen wird durch glutIdleFunc in der main-Funktion.
Da das Hauptaugenmerk der Studienarbeit nicht auf der korrekten Darstellung visueller
Informationsübermittlung bei überlichtschnellen Geschwindigkeiten liegt, erhebt der
Ansatz mittels Veränderung des Blickwinkels die Überlichtgeschwindigkeit zu simulieren
keinen Anspruch auf physikalische Korrektheit. Einzig und allein die Tatsache dem
Benutzer zu verdeutlichen, dass dieser sich mit extrem hohen Geschwindigkeiten bewegt
liefert den Grund für die Implementierung dieses Features.
Bei der Rotation der Kamera in der Szene wurde auf den FTL-Verzerrungseffekt bewusst
verzichtet. Ausnahmslos alle Testpersonen beurteilten den FTL-Verzerrungseffekt in
einer frühen Version des Programms als äußerst irritierend, da dieser bei der Rotation
angewandt den zusätzlichen Anschein eines Zooms auf oder von den Sternen weg
suggerierte. Dies liegt daran, dass durch das langsame, schrittweise Zurücksetzen des
FOV – Winkels die äußeren Ränder des sichtbaren Bereichs hinter den Betrachter
rücken (und damit nicht weiter sichtbar sind), die mittleren Bereiche dehnen sich
scheinbar zurück zu ihren ursprünglichen Maßen. Dem Betrachter wird der Eindruck
vermittelt, er bewege sich während der Rotation von den Sternen weg, nach Beenden
der Rotation wieder zu den Sternen hin.
36
FTL-Effekt bei Zoom vorwärts
Obige Abbildung zeigt den FTL-Effekt bei einem vorwärts gerichteten Zoom. Das grüne
Rechteck zeigt den sichtbaren Bildausschnitt bei einem FOV von 60°, der maximale
Bildausschnitt ist sichtbar bei einem FOV von 145°.
4.9.2 Animierte Billboards
Das Einbinden von Animationen ist nötig um FLARE-Sterne grafisch hervorzuheben. Ein
FLARE-Stern ist ein Stern, welcher in unregelmäßigen Abständen seine Leuchtkraft um
ein Vielfaches erhöht. Der damit verbundene Strahlungsausbruch lässt den Stern für
extrem kurze Zeit sehr hell strahlen.
Im Programm werden FLARE-Sterne durch eine Animationsabfolge dargestellt. Das
eigentliche Bild des Sterns wird in zufälligen Intervallen durch ein wesentlich helleres Bild
des Sterns ersetzt.
Da die verschiedenen Bilder der Animationsfolge zur Laufzeit ständig im Speicher
vorliegen müssen, ist es notwendig, die Image-Pointer, welche die Bilddaten speichern,
global in stars-main.cpp zu definieren.
01
02
ImagePtr
Iredflare0, Iredflare1, Iredflare2, Iredflare3, Iredflare4,
Ihud0, Ihud1, Ihud2, Ihud3, Ihud4, Ihud5, Ihud6, Ihud7;
Innerhalb der display-Funktion – welche laufend vom Programm aufgerufen wird durch
glutIdleFunc in der main-Funktion – wird nun zu bestimmten Zeitpunkten der zu
einem FLARE-Stern gehörige Image-Pointer durch einen anderen Image-Pointer ersetzt.
37
01
02
03
04
05
06
07
08
…
28
29
30
31
32
33
34
35
36
37
if (flaretime>250){ // animation of red flare stars
if (flaretime == 255) {
beginEditCP(redflare);
addRefCP(Iredflare0);
redflare->setImage(Iredflare1);
redflare->imageChanged();
endEditCP(redflare);
}
if (flaretime == 260) {…}
if (flaretime == 275) {
beginEditCP(redflare);
addRefCP(Iredflare4);
redflare->setImage(Iredflare0);
redflare->imageChanged();
endEditCP(redflare);
flaretime = rand()%250;
}
}
flaretime++;
Die Variable flaretime zählt stets bis 250 hoch, dann folgen in 5er-Abständen die
verschiedenen Animationen. Bei Ende der Animation [Zeile 34] wird flaretime auf einen
zufälligen Wert <250 gesetzt, dies bewirkt, dass sich die Animation für den FLARE-Stern
nicht in konstanten Intervallen wiederholt.
Hinweis:
Bei Austausch des Image-Pointers setzt OpenSG den internen Reference-Counter für
den alten Image-Pointer herunter und löscht somit diesen aus dem Speicher. Um dies zu
verhindern muss der Reference-Counter manuell hochgesetzt werden [Zeile 04+30]!
38
4.9.3 Selektierte Sterne
Bei Selektion eines Sterns wird dieser hervorgehoben durch eine Animation. Ein
rotierender Kreis über dem Stern zeigt dem User, welchen Stern er soeben angeklickt
hat. Diese Animation ist wie in 4.9.2 beschrieben umgesetzt worden und als Ergänzung
innerhalb der Methode createStar() eingebunden (vgl. 4.4.1).
Jeder Stern ist an eine Switch-Node gekoppelt. Unter dieser Switch-Node hängt zum
einen der Stern selbst, zum anderen ein texturierte Ebene, welche die Animation des
rotierenden Kreises abspielt. Erst bei Selektion eines Sterns wird jene Animation über
den Switch freigeschaltet. Wählt der User einen anderen Stern oder klickt er auf den
Hintergrund, so wird über den Switch die Animation wieder ausgeblendet.
4.9.4 Bildschirmschoner
Der Bildschirmschoner lässt nach einer vorgegebenen Zeitspanne, in der keine Aktionen
vom User vollzogen wurden, die Kamera um die y-Achse rotieren.
Mit jedem Aufruf der display-Funktion wird die globale Variable screensaver hochgezählt.
Sollte der Wert dieser Variablen größer sein als 3000, so wird bei jedem folgendem
Aufruf der display-Funktion der Kamerawinkel innerhalb von myCamRotation um 1°
hochgezählt (vgl. 4.6.2).
Bei einer Aktion des Users – einem Mausklick – wird der Wert der Variablen screensaver
auf 0 gesetzt.
39
5. Einbinden als Stereoapplikation
Um das Programm stereofähig zu gestalten ist wie in [3, Kapitel Clustering] beschrieben
vorgegangen worden.
Um einen guten 3D-Eindruck zu gewährleisten ist es wichtig, den Abstand der Sterne
zueinander nicht zu hoch zu setzen. Es empfiehlt sich ein Abstand von einer Einheit für
die reale Distanz von einem Lichtjahr zu nehmen.
Die eingeblendeten Informationen werden wie in 4.8 beschrieben durch einen
Szenegraphen realisiert, welcher in sehr geringem Abstand (~0.1 Einheiten) vor die
Kamera gestellt, bzw. unter den Kameraknoten gehangen wird.
Dies bringt jedoch bei Einsatz des Programms auf einer Stereoleinwand einen Nachteil
mit sich: Die eingeblendeten Informationen befinden sich in so naher Parallaxe zum
User, dass die von den Renderservern erzeugten Bilder sehr stark in ihrer Position
variieren.
Um diesen unangenehmen und auch nicht optisch ansprechenden Effekt zu verhindern
muss besagter Szenegraph in größerem Abstand (~10 Einheiten) vor die Kamera
gehangen werden.
40
6. Ausblick
Das Programm bietet einige Möglichkeiten einer zukünftigen Erweiterung. So wäre der
nächste Schritt die Einbindung einer Datenbank und somit Verzicht auf die Textdateien
zur Speicherung der Daten.
Interessant wäre das Einblenden von Linien zwischen den Sternen, zum einen um
Entfernungen benachbarter System zu visualisieren, zum anderen um ggf. Sternbilder
ersichtlich zu machen. Auch könnte hiermit ein 3D-Voronoi-Diagramm realisiert werden,
das zeigt, welche Bereiche des Weltraums von der Schwerkraft der Sterne beeinflusst
werden. GENAUER, wegen versch. Schwerkräften...
In den Sterndaten sind zwei wichtige Punkte bisher nicht beachtet worden, die
Leuchtkraft eines Sterns sowie dessen Eigengeschwindigkeit. Viele sehr erdnahe Sterne
leuchten so schwach, dass man sie eigentlich nicht sehen bzw. erst bei geringer Distanz
sehen kann.
Des weiteren könnte man die Zeit mit in das Programm einfließen lassen, ein Zeitraffer
von einigen Tausend Jahren würde bei eingerechneter Eigenbewegung der Sterne eine
interessante Simulation der solaren Nachbarschaft ergeben. Hierbei müssten aber auch
die verschiedenen Massen der Sterne sowie deren gegenseitige Anziehungskräfte mit
einbezogen werden.
41
7. Fazit
In vorliegender Studienarbeit wurde ein Programm erstellt, welches die stellare
Nachbarschaft unseres Sonnensystems darstellt. Mittels eines neuen Navigationsmodells
ist es dem User vereinfacht, die Orientierung in einem solchen System zu behalten.
Sämtliche Sterne sind als Billboards dargestellt und erlauben es dem User durch
einfaches Austauschen der dazugehörigen Bilddateien komplett neue Skins für das
Programm zu entwerfen. Auch sind die sternrelevanten Daten in einer für den User leicht
zu modifizierenden Form abgelegt.
Die Applikation ist darüber hinaus stereofähig, eine publikumswirksame Präsentation
über 2 Beamer an einer Stereoleinwand ist somit möglich.
Die 6-monatige Arbeit an vorliegendem Programm hat sich als extrem erfahrungsreich
erwiesen. Das Thema war nicht vorgegeben, sondern ist von mir selbst aufgestellt
worden. Somit war maximale Motivation meinerseits gegeben, da Vorkenntnisse in der
Astronomie vorhanden waren und schnell umgesetzt werden konnten. Dennoch blieb
auch viel Raum für neue Erkenntnisse und Erweiterung meines eigenen
zugegebenermaßen teilweise laienhaften Wissens über Astronomie.
Als OpenSG-Anfänger gab es natürlich öfters Punkte, an denen die Arbeit ins Stocken
geraten ist, so zum Beispiel bei dem Einbinden einer eigenen Navigation oder beim
Verwenden von Billboards – zu denen es bisher keine ausreichende Dokumentation gab.
Wie so oft übersieht man am Ende dann die eigentliche Arbeit, die in einem solchen
Projekt steckt und man stellt sich eigens die kritische Frage, ob man nicht hätte mehr
erreichen können. Hierbei sollte man sich aber immer vor Augen halten, dass innerhalb
der 6 Monate ein großer Teil vorerst unbekannten Basiswissens erarbeitet und „in Fleisch
und Blut“ übergehen musste bevor etwas greifbares auf dem Bildschirm erscheinen
konnte.
42
8. Literaturverzeichnis
[1] Ulrich Kaiser. C/C++ Von den Grundlagen zur professionellen
Programmierung. Galileo Press. 2000.
[2] Paul A. Tipler. Physik. Spektrum, Akademischer Verlag. 1998.
[3] OPENSG.
Open Source Scenegraph
(http://www.opensg.org/doc-1.4.0/index.html)
[4] WIKIPEDIA.
(http://www.wikipedia.de)
43
Herunterladen