Der z-Puffer-Algorithmus, Version 3.3
Dieses Programmpaket gibt Ihnen die Möglichkeit, dreidimensionale
Szenen mit dem z-Puffer-Algorithmus in JAVA-Applets darzustellen.
Geschrieben habe ich es 1996, im ersten Jahr meiner Doktorarbeit.
Die StereoImages sind Bilder, die zwei Mal nebeneinander dargestellt
werden und einen räumlichen Effekt verursachen, wenn man sie
durch geschicktes Betrachten miteinander zur Deckung bringt.
Beispielprogramme:
Für die Entwicklung eigener Programme mit dem z-Puffer-Algorithmus
wird nur die Datei zBuffer.java
benötigt; die Darstellung erfolgt, indem von der Klasse
zBuffer eine Unterklasse abgeleitet wird. Wenn ein
Einzelbild berechnet wird, dann braucht in der abgeleiteten Klasse
nur die Funktion init definiert zu werden, in der die Szene
aufgebaut und schließlich repaint() aufgerufen wird.
Die Funktion paint ist bereits implementiert und stellt die
aktuelle Szene dar.
Wenn das Bild interaktiv beeinflussbar
sein soll, dann können zusätzlich Funktionen wie z. B.
handleEvent oder mouseUp definiert werden, weil die
Klasse zBuffer von der Klasse Applet abgeleitet ist.
Analog dazu wird ein Stereobild durch die Ableitung einer Benutzerklasse
von der Klasse StereoImage dargestellt.
Zur Zeit sind von der von zBuffer abgeleiteten Klasse aus folgende
Funktionen aufrufbar:
- Clear() löscht sämtliche Objekte aus der Szene
und beginnt mit dem Aufbau des Bildes von vorne.
- Resize(int,int) legt die Länge und Breite des Bildes
fest. Da dadurch ein neues Array allokiert werden muss, wird das
Bild ebenfalls gelöscht.
- SetBackground(RGB) setzt den Hintergrund auf die gegebene
Farbe; die bereits dargestellten Objekte bleiben dabei erhalten.
Per Voreinstellung ist der Hintergrund transparent.
- SetBackground(PixelGraphic) projiziert die übergebene
Pixelgrafik auf die Hintergrundebene. Die bereits gezeichnete Szene
bleibt dadurch unbeeinflußt.
- SetBackground(URL,String) liest das durch die Parameter
übergebene Bild im GIF-Format ein und stellt es im Hintergrund dar.
- int GetWidth() und int GetHeight() geben die aktuelle
Breite und Höhe des Bildes zurück.
- LightSource(XYZ,float) legt die verwendete Lichtquelle
fest. Dabei ist der erste übergebene Parameter ein Vektor
in die Richtung der Lichtquelle und der zweite eine reelle Zahl
zwischen 0 und 1, die den ambienten Anteil des Lichts angibt.
- Sphere_Raw(XYZ,float,RGB),
Sphere_Untransformed(XYZ,float,RGB)
und Sphere(XYZ,float,RGB)
fügen eine Kugel in die Szene ein, wobei der erste Parameter
der Mittelpunkt, der zweite der Radius und der dritte die Farbe
der Kugel ist. Der Unterschied zwischen den Funktionen ist,
dass die Sphere_Raw mit absoluten Koordinaten rechnet,
d. h., die x- und y-Werte des gezeigten Bildes liegen zwischen
0 und GetWidth() bzw. GetHeight(). Sphere_Untransformed hingegen
fasst die Koordinaten relativ zu den Bildgrenzen auf, so
dass das größte Quadrat, das ganz ins Bild
passt, von (-1,-1,*) bis (1,1,*) geht. Sphere ändert
die Kugel zusätzlich gemäß der eingestellten
Transformationsmatrix (siehe unten).
- Sphere_Raw(XYZ,float,PixelGraphic,XYZ,XYZ,short,short),
Sphere_Untransformed(XYZ,float,PixelGraphic,XYZ,XYZ,short,short)
und Sphere(XYZ,float,PixelGraphic,XYZ,XYZ,short,short)
zeichnen eine texturisierte Kugel. Die erforderlichen Parameter sind:
das Zentrum und der Radius der Kugel, eine Pixelgrafik für die
Textur, Vektoren Richtung Norden und Richtung "Greenwich" und die
Anzahl der Wiederholungen des Texturbildes in senkrechter und
waagerechter Richtung.
- Polygon_Raw(XYZ[],int,RGB),
Polygon_Untransformed(XYZ[],int,RGB)
und Polygon(XYZ[],int,RGB) zeichnen entsprechend ein Polygon,
wobei der erste Parameter das Variablenfeld der Eckpunkte,
der zweite Parameter die Anzahl der Ecken und der dritte die
Farbe des darzustellenden Polygons ist.
- Cylinder_Raw(XYZ,XYZ,float,RGB),
Cylinder_Untransformed(XYZ,XYZ,float,RGB) und
Cylinder(XYZ,XYZ,float,RGB) fügen einen
Zylinder ohne Deckel und Boden in die Szene ein. Durch
die beiden ersten Parameter werden dabei die Endpunkte der
Achse, durch den dritten Parameter der Radius und durch den
vierten Parameter die Farbe vorgegeben.
- Ring_Raw(XYZ,XYZ,float,float,RGB),
Ring_Untransformed(XYZ,XYZ,float,float,RGB) und
Ring(XYZ,XYZ,float,float,RGB) zeichnen einen Kreisring.
Die Eingabeparameter sind: Zentrum der Begrenzungskreise, Normalenvektor
der Fläche, Radius des großen Kreises, Radius des kleinen
Kreises, Farbe des Rings. Um einen vollständigen Kreis zu zeichnen
ist das vierte Argument auf 0 zu setzen.
- Ring_Raw(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int),
Ring_Untransformed(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
und Ring(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
zeichnen einen texturisierten Kreisring. Die Parameter sind:
Zentrum der Begrenzungskreise, Normalenvektor der Fläche,
Radien der beiden Kreise, Pixelgraphik der Textur, Nullrichtung der
Textur und die Anzahl der Wiederholungen der Textur in beiden Richtungen.
- Cone_Raw(XYZ,XYZ,float,float,RGB),
Cone_Untransformed(XYZ,XYZ,float,float,RGB) und
Cone(XYZ,XYZ,float,float,RGB) zeichnen den Mantel eines Kegelstumpfs.
Die Parameter sind: Anfang und Ende der Rotationsachse, Radien der beiden
entsprechenden Begrenzungskreise und die Farbe des darzustellenden Objekts.
- Cone_Raw(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int),
Cone_Untransformed(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
und Cone(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int) zeichnen
einen texturisierten Kegelstumpf. Die Parameter sind:
Anfang und Ende der Rotationsachse, die Radien der beiden
Begrenzungskreise, Pixelgraphik und Nullrichtung der Textur sowie
die Anzahl ihrer Wiederholungen in beiden Richtungen.
- Torus_Raw(XYZ,XYZ,float,float,RGB),
Torus_Untransformed(XYZ,XYZ,float,float,RGB) und
Torus(XYZ,XYZ,float,float,RGB) zeichnen einen Torus.
Die Parameter: Zentrum des Torus, Achsenrichtung, Ringradius,
Schlauchradius und Farbe.
- Torus_Raw(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int) ,
Torus_Untransformed(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
und Torus(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
zeichnen einen texturisierten Torus. Die Parameter sind:
Zentrum des Torus, Achsenrichtung, Ringradius, Schlauchradius,
Pixelgraphik und Nullrichtung der Textur sowie
die Anzahl ihrer Wiederholungen in beiden Richtungen.
- TexturedPlane_Raw(XYZ,XYZ,XYZ,PixelGraphic),
TexturedPlane_Untransformed(XYZ,XYZ,XYZ,PixelGraphic)
und TexturedPlane(XYZ,XYZ,XYZ,PixelGraphic) stellen
ein Parallelogramm mit einer Textur dar. Die übergebenen
Parameter legen die Lage der Eckpunkte oben links, oben rechts und
unten links sowie die Pixelgrafik fest, mit der texturiert werden soll.
(siehe Hilfsklasse PixelGraphic)
- DrawFaster() bewirkt, dass die auf diese Anweisung
folgenden Zylinder und texturierten Parallelogramme
schneller, aber nicht ganz so genau gezeichnet werden.
- DrawSmoother() macht diese Umstellung wieder
rückgängig.
- ClearMatrix() löscht die aktuelle Transformationsmatrix
und stellt die Einheitsmatrix ein.
- Translate(XYZ) bewirkt, dass die darauf folgenden Objekte
um den gegebenen Vektor verschoben erscheinen.
- Scale(float) bewirkt für die folgenden Objekte eine
Skalierung (Vergrößerung bzw. Verkleinerung) um den
gegebenen Faktor.
- RotateX(float), RotateY(float) und
RotateZ(float)
führen eine Rotation um den gegebenen Winkel um die entsprechende
Achse aus.
Bei der Einstellung der Transformation ist zu beachten,
dass die zuletzt ausgeführte Operation nicht relativ
zum Beobachter, sondern relativ zur Szene durchgeführt wird.
- boolean PushMatrix() legt die aktuelle Transformationsmatrix
auf den Stack. Wenn das aus Speichergründen nicht möglich
ist, dann wird der Wert false zurückgegeben und der
Funktionsaufruf hat keine Wirkung.
- boolean PopMatrix() holt die oberste Matrix
vom Stack und macht sie zur aktuellen Transformationsmatrix. Wenn
der Stack leer ist, dann wird der Wert false zurückgegeben
und der Funktionsaufruf hat keine Wirkung.
- boolean RestoreMatrix() macht die oberste Matrix vom Stack
zur aktuellen Transformationsmatrix, ohne sie vom Stack zu entfernen.
Wenn der Stack leer ist, dann wird der Wert false
zurückgegeben und die Einheitsmatrix wieder hergestellt.
- Die Funktion Matrix GetMatrix() gibt den Wert der aktuellen
Transformationsmatrix zurück.
- Die Anweisung SetMatrix(Matrix) stellt die
Transformationsmatrix entsprechend dem übergebenen Parameter ein.
- MultMatrix(Matrix) multipliziert die Transformationsmatrix
mit dem Wert des übergebenen Parameters, führt also die
dadurch bestimmte Transformation aus.
- XYZ GetMousePosition(Event) ist eine Hilfsfunktion, die
die Koordinaten der Mausposition im übergebenen Event in
untransformierte, aber korrekt skalierte Szenenkoordinaten
umwandelt. Die z-Koordinate wird im zurückgegebenen Punkt
auf 0 gesetzt.
- repaint() stellt das aktuelle Bild dar, wie beim normalen
Applet.
Die Klasse StereoImage lässt sich genau wie die Klasse zBuffer
benutzen, wobei natürlich die für das Applet reservierte
Bildbreite das Doppelte der eingestellten Bildbreite sein muss.
Folgende Funktionen sind für Stereo-Images realisiert und haben
die gleiche Wirkung wie beim Applet zBuffer:
- Clear()
- SetBackground(RGB)
( Nur einfarbige Hintergründe ! )
- Resize(int,int)
Diese Funktion ist wichtig für die Initialisierung.
Sie liest automatisch bildschirm- und beobachterspezifische
Werte ein, die über die Parameter des Appletaufrufs
übergeben werden können, aber nicht müssen.
Diese sind:
- EyeDist: Der Augenabstand des Beobachters in
Bildschirmpixeln
- ScreenDist: Der Abstand des Beobachters vom Bildschirm
in Pixeln
- int GetWidth()
- int GetHeight()
- LightSource(XYZ,float)
- Sphere(XYZ,float,RGB)
Sphere_Raw und Sphere_Untransformed sind hier aber
nicht realisiert !
Entsprechendes gilt auch für die anderen Objekte.
- Sphere(XYZ,float,PixelGraphic,XYZ,XYZ,short,short)
- Polygon(XYZ[],int,RGB)
- TexturedPlane(XYZ,XYZ,XYZ,PixelGraphic)
- DrawFaster()
- DrawSmoother()
- Cylinder(XYZ,XYZ,float,RGB)
- Ring(XYZ,XYZ,float,float,RGB)
- Ring(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
- Cone(XYZ,XYZ,float,float,RGB)
- Cone(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
- Torus(XYZ,XYZ,float,float,RGB)
- Torus(XYZ,XYZ,float,float,PixelGraphic,XYZ,int,int)
- ClearMatrix()
- Translate(XYZ)
- Scale(float)
- RotateX(float)
- RotateY(float)
- RotateZ(float)
- boolean PushMatrix()
- boolean PopMatrix()
- boolean RestoreMatrix()
- repaint()
Über die Klassen zBuffer und StereoImage hinaus sind folgende
Hilfsklassen mit ihren Operationen definiert,
die für die Verwendung der Funktionen benötigt werden
und auch bei der Szenenbeschreibung verwendet werden können:
- XYZ stellt einen Punkt oder Vektor im dreidimensionalen Raum
mit seinen Werten x, y und z dar. Ein Objekt dieser Klasse
lässt sich mit einem der beiden Konstruktoren
new XYZ(float,float,float) und new XYZ(XYZ) erzeugen.
- XYZ v.Mult(float) gibt den mit der übergebenen
reellen Zahl multiplizierten Wert des Vektors v zurück.
- XYZ Sum(XYZ,XYZ) addiert die beiden übergebenen
Vektoren und gibt die Summe zurück.
- XYZ Diff(XYZ,XYZ) zieht den zweiten Vektor vom ersten ab.
- XYZ Cross(XYZ,XYZ) bildet das Kreuzprodukt der beiden
übergebenen Vektoren.
- float v.length() berechnet die Länge des Vektors v.
- XYZ v.OrthogonalVector() bestimmt einen zu v orthogonalen
und, falls möglich, von 0 verschiedenen Vektor.
- RGB verkörpert eine Farbe mit den Werten r, g und b
und besitzt die Konstruktoren new RGB(float,float,float) und
new RGB(int). Letzterer ist nützlich, um die in
Pixelgrafiken übliche Darstellung der Farben als Integer
in explizit angegebene RGB-Werte umzuwandeln.
- Matrix stellt eine Transformationsmatrix dar. Der Konstruktor
new Matrix() stellt die Einheitsmatrix her, der
Konstruktor new Matrix(Matrix) erzeugt eine Kopie einer
übergebenen Matrix.
- XYZ m.Transform(XYZ) führt die Transformationsmatrix m
auf den übergebenen Punkt aus.
- XYZ m.VectorTransform(XYZ) tut das entsprechende mit
einem Vektor, d. h., ohne Verschiebungskonstante.
- m.Translate(XYZ) multipliziert die Matrix m mit einer
Translation um den übergebenen Vektor.
- m.Scale(float) multipliziert die Matrix mit einer Skalierung
um den übergebenen Faktor.
- m.RotateX(float), m.RotateY(float) und
m.RotateZ(float) multiplizieren die Matrix mit der entspechenden
Rotationsmatrix um den übergebenen Winkel.
- m.Mult(Matrix) multipliziert die Matrix mit einer explizit
gegebenen anderen Matrix.
- float m.Determinant() berechnet die Determinante der
Matrix m und gibt sie als Funktionswert zurück.
- float m.Scaling() versucht, den zur Matrix gehörenden
Skalierungswert zu bestimmen, mit dem Längen, Radien u. ä.
multipliziert werden müssen. Es wird dabei vorausgesetzt,
dass die Matrix eine Ähnlichkeitsabbildung darstellt.
- Die Klasse PixelGraphic enthält alle Informationen
einer Pixelgrafik in leicht einlesbarer Form. Der Konstruktor
new PixelGraphic(Applet,URL,String) liest bereits bei der
Initialisierung ein Bild im GIF-Format ein, dessen Position im
Internet durch die übergebene URL und Zeichenkette bestimmt
wird. Im ersten Parameter muss das aufrufende Applet
übergeben werden, damit der Einlesevorgang funktioniert.
Neuerdings gibt es auch einen Feedback-Konstruktor
new PixelGraphic(zBuffer), der die Information eines zBuffer-Bildes
wieder einliest.
- int g.GetPixel_RAW(int,int) liest das Pixel an der
durch die übergebenen ganzzahligen Koordinaten angegebenen
Stelle ein und gibt seinen Farbwert im für Pixelgrafiken
üblichen Integer-Format zurück.
- RGB GetPixel(float,float) übergibt ebenfalls den
Pixelwert, mit den beiden
Unterschieden, dass die Koordinaten als float-Werte zwischen
0 und 1 interpretiert werden und die Farbe als Objekt der Klasse
RGB zurückgegeben wird.