Eine Einführung in JOGL

Größe: px
Ab Seite anzeigen:

Download "Eine Einführung in JOGL"

Transkript

1 Eine Einführung in JOGL WS 2008/09 Klarinette Gicks und Gacks, Gacks und Gicks, Ohne Holz Ise nix. Klapperl auf, Löcherl zu, Glu, glululu. Josef Weinheber

2 Inhaltsverzeichnis 2

3 1 Übersicht JOGL ist eine Java-Erweiterung, die i.w. die Konzepte des Pakets OpenGL zur Verfügung stellt. 1.1 Was ist OpenGL? OpenGL ist eine plattformunabhängige Graphikbibliothek, die inzwischen zu einem weltweiten Standard für 3D-Graphikprogrammierung geworden ist. Sie wird sehr vielfältig verwendet: In der Industrie, in Forschungszentren, in der Spieleprogrammierung und in der Lehre. Die Plattformunabhängigkeit wurde dadurch erreicht, dass OpenGL tatsächlich nur die Spezifikation einer Bibliothek ist, für die verschiedenste Implementierungen existieren, teilweise direkt von Graphikkarten unterstützt Was leistet OpenGL? Hier sind einige charakteristische Elemente: Es werden grundlegende geometrische Objekte bereitgestellt wie Geraden/Strecken, Polygone, Dreiecksnetze, Kugeln, Quader, Quadriken (Ellipsoide, Paraboloide, Hyperboloide), spezielle Kurven und Flächen. Dazu kommen die besprochen Transformationen (Streckung, Drehung, Spiegelung, Scherung), Projektionen (Parallel- und Zentralprojektion) sowie Kameradefinitionen. OpenGL unterstützt Bilddarstellung (Rendering) in hoher Qualität, Entfernen verdeckter Flächen, mehrfache Lichtquellen, Oberflächenmaterialien und -texturen, Farbverläufe und Nebel. Es gibt Datenstrukturen zur gepufferten Verwaltung von Objektsammlungen und zum Aufbau hierarchischer Modelle; schließlich können Objekte interaktiv ausgewählt werden. Auch Implementierungsdetails wie Pixelansteuerung, Anti-Alias, Bewegungsunschärfe, Tiefeneffekte und weiche Schatten werden unterstützt. In OpenGL werden die Bereiche der Bildsynthese (Rendering) und der Interaktion (Eingabe und Fensteransteuerung) zunächst getrennt: OpenGL in engeren Sinn befasst sich nur mit der Synthese; alle zugehörigen Funktionen beginnen mit gl. 1 dann ist es natürlich schnell 3

4 Die Zusatzbibliothek GLU (OpenGL Utility Library) stellt reichhaltigere Zeichenprimitive zur Verfügung als OpenGL selbst, z. B. Kurven und Flächen und Funktionen zur Spezifikation von 3D-Szenerien. Alle GLU- Funktion beginnen mit glu. Eine weitere Zusatzbibliothek GLUT (OpenGL Utility Toolkit) behandelt die Interaktion. Sie stellt Funktionen zum Aufbau von Fenstern und zum Behandeln von Tastatur- und Mausereignissen zur Verfügung. Außerdem enthält sie einige rudimentäre Möglichkeiten zum Aufbauen grafischer Benutzeroberflächen. Schließlich definiert GLUT noch einige komplexere geometrische Objekte Polyeder und die klassische Graphik-Teekanne. Alle GLUT-Funktionen beginnen mit glut. Meist unterscheidet man nicht so fein und bezeichnet mit OpenGL das Gesamtpaket dieser drei Bibliotheken. 2 Erste Schritte mit JOGL 2.1 Grundstrukturen In JOGL sind nun die Funktionen von OpenGL in einer Java-kompatiblen Weise realisiert. Den drei Teilen von OpenGL entsprechen eigene Klassen GL, GLU und GLUT. Um Konzepte aus diesen Teilen nutzen zu können, muss man jeweils ein Objekt der betreffenden Klasse erzuegen und diesem dann entsprechende Methodenaufrufe schicken. Außerdem muss man das Interface GLEventListener implementieren. Dieses Interface hat folgende Methoden: public void display(glautodrawable gldrawable): In dieser Methode wird die Szenerie erstellt und die Kamera positioniert. Die Details werden später an den Beispielen erläutert. public void displaychanged(glautodrawable gldrawable, boolean modechanged, boolean devicechanged): Diese Methode soll aufgerufen werden, wenn der Bildschirmmodus geändert wird, wird aber gegenwärtig nicht unterstützt. Der Rumpf dieser Methode sollte deshalb am besten leer bleiben. public void init(glautodrawable gldrawable): Diese Methode wird einmal beim Erzeugen aufgerufen und eignet sich, um Variablen oder Eigenschaften zu initialisieren. public void reshape(glautodrawable gldrawable, int x, int y, int width, int height): Diese Methode behandelt das Verändern der Fenstergröße und das Verschieben des Fensters. Auch hier werden die Details später erläutert. 4

5 Um das erzeugte Bild nicht nur abstrakt im Rechner zu haben, sollte man es auf einem GLCanvas ausgeben lassen. Diese Klasse erbt von Canvas und lässt sich einem Frame hinzufügen. 2.2 Beispiel: Ein einfaches Fenster Der folgende Code erzeugt ein schwarzes Fenster ohne jegliche Graphik, das sich nicht in gewohnter Weise schließen lässt. import java.awt.*; import java.awt.event.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; import com.sun.opengl.util.*; public class Beispiel_1 { static class WinRenderer extends GLCanvas implements GLEventListener { //GL und GLU zum Aufrufen der Graphikfunktionen private GL gl; private GLU glu; //Konstruktor public WinRenderer(){ super(); //Erstellen des Fensters public void display(glautodrawable gldrawable){ //GL-Objekt holen gl = gldrawable.getgl(); //Bildpuffer leeren gl.glclear(gl.gl_color_buffer_bit); //und ab geht die Post gl.glflush(); //nicht implementiert public void displaychanged(glautodrawable gldrawable, boolean modechanged, boolean devicechanged){ //hier gibt es nichts zu initialisieren public void init(glautodrawable gldrawable){ 5

6 //Auch das Verändern des Fensters interessiert uns nicht public void reshape(glautodrawable gldrawable, int x, int y, int width, int height){ public static void main(string[] args) { //Frame mit Titel erzeugen Frame frame = new Frame("Ein leeres Fenster"); //neuen WinRenderer erzeugen WinRenderer canvas = new WinRenderer(); //zum Frame hinzufügen frame.add(canvas); //Größe setzen frame.setsize(640, 480); //und anzeigen frame.show(); 3 Kamera und Projektionen 3.1 Modellmatrix und Projektionsmatrix JOGL hält intern zwei 4D-Matrizen: Die Modellmatrix M enthält die Gesamttransformation, der die ganze Modellwelt unterworfen wird, bevor die Projektion auf die 2D-Bildfläche stattfindet. Insbesondere ist dabei der Wechsel ins Kamera-Koordinatensystem enthalten. Die Projektionsmatrix P gibt an, ob Parallel- oder Zentralprojektion stattfindet. Zum Anzeigen des Bildes wird dann P M auf alle Objektkoordinaten angewendet. Beide Matrizen können schrittweise aus Grundmatrizen durch Matrixmultiplikation zusammengesetzt werden; auch explizite Angabe ist möglich. Die jeweils aktuelle Modell- oder Projektionsmatrix wird mit C ( current ) bezeichnet. Viele JOGL-Funktionen verändern C, und wir werden oft die Veränderung in algebraischer Form angeben. Mit void GL.glMatrixMode (int mode); 6

7 wird ausgewählt, ob mit C die aktuelle Modell- oder Projektionsmatrix gemeint ist; die entsprechenden Parameter sind GL.GL_MODELVIEW bzw. GL.GL_PROJECTION; die Voreinstellung ist C = M. Zur Initialisierung der jeweiligen Matrix dient void GL.glLoadIdentity (void); mit der Wirkung C E (E ist die Einheitsmatrix). Einfache Transformationen werden bewirkt durch folgende Funktionen: void GL.glTranslatef (float x, y, z); C C T(x, y, z) void GL.glScalef (float x, y, z); C C S(x, y, z) void GL.glRotatef (float angle, x, y, z); C C R(angle, x, y, z) 3.2 Die Kamera Sie wird definiert durch void GLU.gluLookAt (double eyex, eyey, eyez, // Augpunkt centerx, centery, centerz, // Hauptpunkt upx, upy, upz); // Obenvektor Diese Funktion wird üblicherweise in der Methode display aufgerufen. 3.3 Projektionen Eine Orthogonalprojektion wird spezifiziert durch void GL.glOrtho (double left, right, bottom, top, near, far); Eine Zentralprojektion ist gegeben durch void GLU.gluPerspective (double alpha, aspect, near, far); Warum die Orthogonalprojektion und die Zentralprojektion in verschiedenen Klassen implementiert sind, ist unklar. 3.4 Der Bildausschnitt (Viewport) Manchmal will man das Frustum nicht auf dem Gesamtschirm anzeigen, sondern nur auf einem Ausschnitt daraus. Dazu dient 7

8 void GL.glViewport (int x, y, width, height); x und y geben die linke untere Ecke des Ausschnitts an. Im Gegensatz zu Weltund Bildkoordinaten werden hier Pixelkoordinaten verwendet. Achtung: Stimmt das Verhältnis von width und height nicht mit dem des Frustums überein, kommt es zu Verzerrungen. Bildausschnitt und Projektion werden meist in der Methode reshape gesetzt. 4 Grundlegende Graphikelemente 4.1 Beispiel: Ein Fenster mit einfacher Graphik Das folgende Programm erzeugt ein schwarzes Fenster, auf dem ein weißes Dreieck zu sehen ist. Der Code wird im Anschluß an den Quelltext besprochen. import java.awt.*; import java.awt.event.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; import com.sun.opengl.util.*; public class Beispiel_3 { static class WinRenderer extends GLCanvas implements GLEventListener { private GL gl; public WinRenderer(){ super(); //Erzeugen der Szenerie public void display(glautodrawable gldrawable){ //GL-Objekt holen gl = gldrawable.getgl(); //Bildpuffer leeren gl.glclear(gl.gl_color_buffer_bit); //Modellmatrix initialisieren gl.glloadidentity(); 8

9 //Kamera positionieren glu.glulookat(0,0,0.5,0,0,0,0,1,0); //geschlossenen Linienzug beginnen gl.glbegin(gl.gl_line_loop); //Punkte setzen gl.glvertex3f(-0.3f,-0.3f,0f); gl.glvertex3f(0f,0.3f,0f); gl.glvertex3f(0.3f,-0.3f,0f); //Linienzug beenden gl.glend(); //Pufferinhalt weitergeben gl.glflush(); public void displaychanged(glautodrawable gldrawable, boolean modechanged, boolean devicechanged){ public void init(glautodrawable gldrawable){ //Reaktion auf Fensteränderungen public void reshape(glautodrawable gldrawable, int x, int y, int width, int height){ //GL-Objekt holen gl = gldrawable.getgl(); //Bildausschnitt im Fenster positionieren gl.glviewport(0,0,width,height); //Auf Projektionsmatrix umschalten gl.glmatrixmode(gl.gl_projection); //Projektionsmwtrix initialisieren gl.glloadidentity(); //Orthogonalprojektion wählen gl.glortho(-1,1,-1,1,-1,1); //und wieder auf Modellmatrix zurücksetzen gl.glmatrixmode(gl.gl_modelview); public static void main(string[] args) { //Frame mit Titel erzeugen Frame frame = new Frame("weißes Dreieck auf schwarzem Grund" //neuen WinRenderer erzeugen WinRenderer canvas = new WinRenderer(); //GLEventlistener hinzufügen canvas.addgleventlistener(canvas); //GLCanvas auf den Frame kleben frame.add(canvas); //zum besseren Schließen :-) frame.addwindowlistener(new WindowAdapter() { 9

10 public void windowclosing(windowevent e) { System.exit(0); ); //Größe setzen frame.setsize(640, 480); //anzeigen frame.show(); //GLCanvas in den Vordergrund holen canvas.requestfocus(); Zunächst wollen wir uns die display-methode dieses Beispiels ansehen. In der Zeile gl = gldrawable.getgl(); wird vom übergebenen GLAutoDrawable-Objekt das GL-Objekt ausgelesen. Die Klasse GL stellt viele Methoden zum Erstellen und Zeichnen einer Szenerie zur Verfügung. Mit glu = new GLU(); wird eine Instanz von GLU erzeugt. Auch hier sind viele Methoden zum Zeichnen und Positionieren von Szenerien zu finden. Die Anweisung gl.glclear(gl.gl_color_buffer_bit); leert den Bildpuffer. Mittels gl.glloadidentity(); wird die Modellmatrix initialisiert. Da der Defaultwert für die Matrix die Modellmatrix ist (siehe das Kapitel über Kamera und Projektionen), muß man nicht explizit auf den Modellmatrixmodus umschalten. Das Initialisieren entspricht einem push der Einheitsmatrix auf den (leeren) Matrixkeller. 10

11 Die Positionierung der Kamera geschieht mit glu.glulookat(0,0,0.5,0,0,0,0,1,0); Warum diese Funktion in GLU und nicht in GL enthalten ist, mag jeder ebenso wie den Grund für die Unterteilung in GL, GLU und GLUT selbst herausfinden. In unserem Fall wird die Kamera im Punkt (0,0,0.5) positioniert, blickt in Richtung des Ursprungs (0,0,0) und ist derart gedreht, daß der Vektor (0,1,0) im Bild nach oben zeigt. Die Zeile gl.glbegin(gl.gl_line_loop); kündigt den Beginn eines geschlossenen Linienzuges an, dessen Punkte durch gl.glvertex3f(-0.3f,-0.3f,0f); gl.glvertex3f(0f,0.3f,0f); gl.glvertex3f(0.3f,-0.3f,0f); festgelegt sind. Das Ende dieses Linienzuges wird durch gl.glend(); markiert. GL.glBegin(int figure) kann noch andere Argumente außer GL.GL_LINE_LOOP haben; dazu später mehr. Die letzte Zeile gl.glflush(); gibt den aktuellen Pufferinhalt an das Fenster weiter. Die Methoden displaychanged und init bleiben unimplementiert: Für displaychanged wurde der Grund bereits erläutert, und init bleibt leer, weil wir nichts zu initialisieren haben. Die reshape-methode ist für das Neuzeichnen des Fensters bei Format- oder Ortsänderungen desselben zuständig. Die aktuelle Position des Fensters auf dem Bildschirm wird in Gestalt der int-werte x und y übergeben. Die Fensterbreiteund höhe erhält die Methode durch die Integer width bzw. height. Nach dem Auslesen eines GL-Objekts durch gl = gldrawable.getgl(); 11

12 wird mittels gl.glviewport(0,0,width,height); der Viewport gesetzt. Hier wird die linke untere Ecke des Bildes in die linke untere Ecke des Fensters (dafür sind die beiden ersten Nullen verantwortlich) gelegt und die Breite und die Höhe des Bildes genau auf die Fensterbreite- und höhe gesetzt. Die übergebenen int-werte rechnen alle in Pixeln. gl.glmatrixmode(gl.gl_projection); schaltet auf die Modellmatrix um, die dann durch gl.glloadidentity(); auch gleich initialsiert wird (vgl. das Vorgehen in display). Nun gilt es noch, die Projektion zu spezifizieren. Der Aufruf gl.glortho(-1,1,-1,1,-1,1); spezifiziert eine Parallelprojektion mit einem quaderförmigen Frustum, dessen linke vordere Ecke ( 1, 1, 1) (also hinter der Kamera) und dessen rechte vordere Ecke (1, 1, 1) ist. Allgemein beschreibt GL.glOrtho(double umin, umax, vmin, vmax, near, far) einen Quader mit (umin, vmin, near) als linker vorderer und (umax, vmax, far) als rechter hinterer Ecke. Hierbei ist darauf zu achten, daß umin < umax, vmin < vmax und near < far gelten, vgl. auch das Skript von Toby Howard, Seite 61. Der Koordinatenursprung, bezüglich dessen der Quader ermittelt wird, ist die Kameraposition, die Richtungen links/rechts, oben/unten und vorn/hinten werden durch die Blickrichtung und den view-up-vektor festgelegt. Da wir uns noch im Projektionsmatrixmode befinden, setzen wir mit gl.glmatrixmode(gl.gl_modelview); den Matrixmode wieder auf die Modellmatrix zurück. In der main-methode passiert nichts besonders aufregendes; sie erzeugt einen Frame, fügt ihm einen von GLCanvas abgeleiteten WinRenderer hinzu und zeigt das Ganze an. 4.2 Weitere Graphikelemente Punkte Wie bereits angedeutet kann man zwischen GL.glBegin(int mode) und GL.glEnd noch mehr anstellen als nur einen Linienzug zu zeichnen. Beginnen 12

13 wir mit dem einfachsten, einem kleinen einsamen Punkt. Ein Punkt im R 3 wird definiert durch: void GL.glVertex3f (float x, y, z); Analog dazu gibt es eine Fassung, die drei double-werte erwartet: void GL.glVertex3d (double x, y, z); Punkte im R 2 werden durch zwei float- oder double-werte charakterisiert und mittels der Funtionen void GL.glVertex2f (float x, y) bzw. void GL.glVertex2d (double x, y) erzeugt Gruppierung Mehrere Punkte können zu einer Figur zusammengesetzt werden mit void GL.glBegin (int mode); void GL.glEnd (void); Dabei gibt mode die Art der Gruppe an: GL.GL_POINTS: unverbundene Punkte GL.GL_LINES: bildet Punktepaare, von denen jedes verbunden wird, aber nicht mit den anderen zusammenhängt. GL.GL_LINE_STRIP: Die Punkte werden zu einem Kantenzug zusammengefügt. GL.GL_LINE_LOOP: Der Kantenzug wird zu einem Kreis geschlossen. GL.GL_TRIANGLES: Unverbundene Dreiecke aus Dreiergruppen von Punkten. GL.GL_TRIANGLE_STRIP: Bildet Dreiecke aus v 0, v 1, v 2, v 3, v 4,... wie folgt: v 0 v 1 v 2, v 2 v 1 v 3, v 2 v 3 v 4, v 4 v 3 v 5,... 13

14 Damit wird ein Dreiecksnetz als Ausschnitt einer angenäherten 3D-Fläche v 2 v 4 v 0 v 1 v 3 gebildet. Abbildung 1. GL_TRIANGLE_STRIP GL.GL_TRIANGLE_FAN: Zeichnet Dreiecke v 0 v 1 v 2, v 0 v 2 v 3, v 0 v 3 v 4, d.h. einen Fächer mit v 0 im Zentrum. v 3 v 2 v 4 v 0 v 1 Abbildung 2. GL.GL_TRIANGLE_FAN GL.GL_QUADS: Unverbundene Vierecke aus Vierergruppen von Punkten. GL.GL_QUAD_STRIP: analog zu GL.GL_TRIANGLE_STRIP: v 4 v 6 v 0 v 2 v 1 v 3 v 5 v 7 Abbildung 3. GL.GL_QUAD_STRIP GL.GL_POLYGON: verbindet Punkte zu einem Polygonzug. Das Polygon muss konvex sein und darf sich nicht selbst überschneiden. Sonstige Polygone müssen in konvexe zerlegt werden (Tesselierung). 14

15 Zu Linien und Polygonen können zusätzliche Attribute spezifiziert werden; void GL.glLineWidth (float width); stellt die Linienbreite ein. void GL.glLineStipple (int factor, short pattern); definiert die Strichelung (muss zuerst eingeschaltet werden, s. u.); die Möglichkeiten werden binär codiert. void GL.glPolygonMode (int face, mode) mit face { GL.GL_FRONT, GL.GL_BACK, GL.GL_FRONT_AND_BACK und mode { GL.GL_FILL, GL.GL_LINE Der Parameter face erlangt erst später Bedeutung für uns, über mode kann eingestellt werden, ob ein Polygon o.ä. ausgefüllt oder nur als Liniengerippe erscheint Graphikfunktionen in GLUT GLUT stellt einige komplexe Körper vordefiniert zur Verfügung. GLUT.glutWireCube (double size) zeichnet einen Würfel der Seitenlänge size mit Mittelpunkt im Ursprung (in Weltkoordinaten) als Drahtmodell. GLUT.glutSolidCube (double size) analog, aber als festen Körper. GLUT.glutWireSphere (double radius, int slices, stacks) GLUT.glutSolidSphere (double radius, int slices, stacks) Kugel mit Radius radius und Mittelpunkt im Ursprung. slices gibt die Anzahl der Längengrade, stacks die der Breitengrade an. GLUT.glutWireCone (double base, height, int slices, stacks) GLUT.glutSolidCone (double base, height, int slices, stacks) Kegel mit Grundradius base und Höhe height; die Grundfläche liegt auf der xy-ebene und die z-achse ist die Kegelachse. slices, stacks wirken wie bei den Kugeln. GLUT.glutWireTorus (double innerradius, outerradius, int nsides, rings) GLUT.glutSolidTorus (double innerradius, outerradius, int nsides, rings) Torus mit Mittelpunkt im Ursprung und der z-achse als Achse. nsides ist die Zahl der Seiten in jedem Radialschnitt, rings die Zahl der Radialschnitte. 15

16 Die platonischen Polyeder (jeweils mit Mittelpunkt im Ursprung) lassen sich mit folgenden Funktionen zeichnen: void GLUT.glutWireTetrahedron (void) Radius 3 void GLUT.glutSolidTetrahedron (void) Radius 3 void GLUT.glutWireOctahedron (void) Radius 1 void GLUT.glutSolidOctahedron (void) Radius 1 void GLUT.glutWireDodecahedron (void) Radius 3 void GLUT.glutSolidDodecahedron (void)radius 3 void GLUT.glutWireIcosahedron (void) Radius 1 void GLUT.glutSolidIcosahedron (void) Radius 1 void GLUT.glutWireTeapot (double scale) void GLUT.glutSolidTeapot (double scale) Die klassische Teekanne, um den Faktor scale gestreckt. 5 Weiteres Zubehör 5.1 Farben Im RGB-Farbmodell wird jede Farbe durch ihren Rot-, Grün- und Blauanteil dargestellt; dazu gibt man in JOGL Bruchzahlen in [0, 1] an. Der Zusammenhang zwischen den Farben wird durch folgenden Farbwürfel beschrieben: C G W Y Schwarz S = (0.0, 0.0, 0.0) Weiß W = (1.0, 1.0, 1.0) Cyan C = (0.0, 1.0, 1.0) Magenta M = (1.0, 0.0, 1.0) Gelb Y = (1.0, 1.0, 0.0) S R B M Abbildung 4. Farbwürfel 16

17 Auf der Raumdiagonalen zwischen S und W liegen die Graustufen. Dieses Farbmodell ist die Voreinstellung in JOGL. Die aktuelle Zeichenfarbe setz man mit void GL.glColor3f (float red, green, blue); 5.2 Elimination verdeckter Flächen JOGL stellt hierfür eigene Befehle zur Verfügung; auf den algorithmischen Hintergrund werden wir später eingehen. Per Voreinstellung zeichnet JOGL die Objekte einer Szenerie in der Reihenfolge, wie sie im Programm erscheinen. Das führt insbesondere bei Animationen oft zu grotesken Verdeckungen. JOGL unterstützt hier die Tiefenpufferung (z-buffering). Dabei wird für jedes Pixel in einem speziellen Feld Tiefeninformation gespeichert. Bei der Aufbereitung für ein Objekt wird beim Schreiben des entsprechenden Pixels jeweils geprüft, ob es zu einem Punkt geringerer Tiefe gehört, als bisher vermerkt; dann wird der alte, durch das neue Objekt verdeckte, Pixelwert überschrieben, ansonsten ändert er sich nicht. Die Tiefenpufferung schaltet man so ein: Der Aufruf von GLUT.glutInitDisplayMode wird zu void GLUT.glutInitDisplayMode (GLUT_DOUBLE GLUT_DEPTH); In der display-funktion muss zu Beginn auch der Tiefenpuffer gelöscht werden: void glclear (GL.GL_COLOR_BUFFER_BIT GL.GL_DEPTH_BUFFER_BIT); und die Tiefenpufferung ermöglicht werden: void GL.glEnable (GL.GL_DEPTH_TEST); 6 Animation Bis jetzt haben wir uns nur mit der Erzeugung von statischen Blidern beschäftigt; nun wollen wir uns noch damit vertraut werden, wie man unter JOGL die Bilder zum Laufen bringen kann. Dazu dient die Animator-Klasse. Ihr Konstruktor hat entweder kein Argument oder bekommt ein GLAutoDrawable-Objekt übergeben. Im Regelfall wird das ein GLCanvas sein, der mittels des Animators zum Leben erweckt wird. Durch den Aufruf der start-methode des Animators 17

18 wird zuerst die init-methode des übergebenen Objekts aufgerufen, anschließend wird in einer Endlosschleife immer wieder die display-methode aufgerufen, unterbrochen von eventuellen Einschüben der reshape-methode, falls das Fenster verschoben oder in der Größe geädert wurde. Der Animator verfügt unter anderem auch über eine wait-methode, mit der der Lauf der Ereignisse für eine gewisse Zeit angehalten werden kann, und über eine stop-methode, mit der man ihn unbegrenzte Zeit aufhalten kann. Hierzu vergleiche man auch Beispiel 5 auf der Vorlesungs-Webseite. Dieses Vorgehen führt zwar zum Ziel, hat aber einige Nachteile: Die CPU-Auslastung steigt je nach Rechner auf bis zu 95% Die Geschwindigkeit, mit der die Anzeige erfolgt, hängt von der Leistungsfähigkeit des Rechners ab Der Grund hierfür ist, daß der Animator so ost wie möglich die Methoden aus dem übergebenen GLAutoDrawable-Objekt abzuarbeiten versucht. Die dadurch entstehenden Probleme kann man zu einem großen Teil mit der Verwendung eines FPSAnimators umgehen. Er besitzt die gleichen Methoden wie ein normaler Animator, bekommt aber im Konstruktor neben einem GLAutoDrawable- Objekt noch einen int-wert übergeben, der angibt, wie oft pro Sekunde das GLAutoDrawable-Objekt abgearbeitet werden soll. Ein solcher FPSAnimators wird im Beispiel 5b auf der Webseite eingesetzt. 7 Bezier-Kurven JOGL bietet die Möglichkeit, Bezier-Kurven nach der Angabe von Stützpunkten berechnen zu lassen. Dazu betrachten wir das kleine Demoprogramm Bezier.java, zu finden auf der Webseite unter Beispiele. Im Vergleich zu den bisherigen Programmen füheren wir hier ein float-array control_points ein: float [] control_points = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f; Dieses Array spezifiziert die Stützpunkte unserer Bezier-Kurve. Wie die Einträge vom Programm interpretiert werden, sehen wir in Bälde. Zur weiteren Verwendung muß dieses float-array noch mittels buf = FloatBuffer.wrap(control_points); in einen FloatBuffer eingepackt werden. 18

19 Am wichtigsten für das Ergebnis ist die Zeile gl.glmap1f(gl.gl_map1_vertex_3, 0.0f, 1.0f, 3, 4, buf); Zuerst wird mit gl.gl_map1_vertex_3 die Art der Auswertung festgelegt: Es sollen Punkte im R 3 berechnet werden. Die beiden float-werte 0.0f und 1.0f geben den Bereich an, in den der Parameter t der Bezier-Kurven- Funktion sich bewegen soll. Der int-wert 3 ist wichtig für die Interpretation des control_point-array als Stützpunkte: Ein neuer Stützpunkt beginnt nach jedem dritten Eintrag im control_point-array. In unserem Beispiel sind die Kontrollpunkte (da wir im R 3 auswerten) die Punkte (0, 0, 0), (0, 1, 0), (1, 1, 0) und (1, 0, 0), insbesondere ist also (0, 0, 0) der Anfangspunkt und (1, 0, 0) der Endpunkt; die beiden anderen Punkte sind Stützpunkte. Die 4 gibt die Anzahl der Stützpunkte, also die Ordung der Bezier-Kurve an, und buf die zu verwendenden Kontrollpunkte. Die Berechnung der Kurvenpunkte findet in der Zeile gl.glevalcoord1f(i/num); statt. Das Argument dieser Funktion ist der Wert, der in der vorher spezifizierten Bezier-Kurve für t eingesetzt wird. In unserem Fall wird der Bereich [0, 1] in num Teilbereiche aufgespalten, d.h., es werden num + 1 Punkte berechnet und durch die GL_LINE_STRIP-Umgebung durch einen Linienzug verbunden. Die GL.glEvalCoord1f-Methode kann verschiedene Rückgabewerte haben; in diesem Kontext wird voon ihr ein FloatBuffer erwartet, der dann als Punkt im R 3 interpretiert wird. Das Ergebnis dieses Programmes ist sehr symmetrisch, was auf die Wahl der Stützpunkte zurückzuführen ist. Es ist interessant, die Änderungen zu beobachten, die sich ergeben, wenn man den num-wert und die Stützpunkte verändert. 8 Quadriken 8.1 Grundbegriffe Unter Quadriken versteht man geometrische Objekte, die durch Gleichungen der Form P(x, y, z) = 0 mit einem Polynom P zweiten Grades in den Koordinaten x, y, z beschrieben werden können. Darunter fallen Kugeln (allgemeiner Ellipsoide), Paraboloide, Hyperboloide und Zylinder, aber auch (Ausschnitte von) Kreisscheiben. Ausgeschrieben hat die allgemeine Quadrikgleichung die Form a 11 x 2 + a 22 y 2 + a 33 y 2 + 2a 12 xy + 2a 23 yz + 2a 13 xz + b 1 x + b 2 y + b 3 z + c = 0. 19

20 In Matrix-Vektor-Schreibweise kann man das auch formulieren als (x y z) T a 11 a 12 a 13 a 12 a 22 a 23 x y + (b 1 b 2 b 3 ) T x y + a 10 = 0. a 13 a 23 a 33 z z Die obige Form des Polynoms wurde gewählt, damit sich eine symmetrische Matrix ergibt; sie läßt sich durch Halbieren der gemischten Koeffizienten immer erreichen. In JOGL werden Quadriken über GLUquadric-Objekte verwaltet. Zur Erzeugung eines neuen GLUquadric-Objekts dient GLUquadric glu.glunewquadric(); Dieses Objekt muß dann in einer Variablen gespeichert werden, um es weiter verwenden zu können. 8.2 Die Zeichenfunktionen Die Funktion void glu.glusphere (GLUquadric quad, double radius, int slices, int stacks); zeichnet eine Kugel mit dem gegebenen Radius um den Ursprung (0 0 0). Dabei gibt slices die Anzahl der Längengrade und stacks die Anzahl der Breitengrade ein (Achse in z-richtung). Werden Texturkoordinaten miterzeugt (siehe unten), variiert die t-koordinate von 0.0 bei z = radius bis 1.0 bei z = radius und zwar linear entlang den Längengraden. Dagegen variiert die s-koordinate von 0.0 auf der positiven y-achse zu 0.25 auf der positiven x-achse, dann zu 0.5 auf der negativen y- Achse, dann zu 0.75 auf der negativen x-achse und schließlich zu 1.0, um den Umfangskreis auf der positiven y-achse zu schließen. Die Funktion void glu.glucylinder (GLUquadric quad, double baseradius, double topradius, double height, int slices, int stacks); zeichnet einen Kegelstumpf mit Radius baseradius bzw. topradius ein Bodenbzw. Deckfläche. Für topradius = 0 ergibt sich ein echter Kegel. Die Bodenfläche liegt in der xy-ebene, die Höhe ist height und die Achse ist wieder die z-achse. slices und stacks haben analoge Bedeutung wie bei der Kugel. Achtung: Der Kegelstumpf ist oben und unten nicht geschlossen (außer für topradius = 0); die Boden- und Deckfläche werden nicht mitgezeichnet. 20

21 Werden Texturkoordinaten miterzeugt, variiert die t-koordinate linear von 0.0 bei z = 0 bis 1.0 bei z = height. Die s-texturkoordinaten werden genau wie bei der Kugel erzeugt. Die Funktion void glu.gludisk (GLUquadric quad, double innerradius, double outerradius, int slices, int rings); zeichnet eine Kreisscheibe auf der xy-ebene mit Radius outerradius und einem konzentrischen kreisrunden Loch mit Radius innerradius. Ist innerradius = 0, wird kein Loch gezeichnet. Die Scheibe wird in slices Sektoren und rings konzentrische Ringe um die z-achse unterteilt. Die positive z-richtung zählt als Außenseite der Scheibe. Die Texturkoordinaten sehen folgendermaßen aus: Sei R = outerradius. Dann hat man die Entsprechungen Die Funktion (x, y, z) (s, t) (R, 0, 0) (1, 0.5) (0, R, 0) (0.5, 1) ( R, 0, 0) (0, 0.5) (0, R, 0) (0.5, 0) void glu.glupartialdisk (GLUquadric quad, double innerradius, double outerradius, int slices, int rings, double startangle, double sweepangle); zeichnet einen Ausschnitt aus einer Kreisscheibe auf der xy-ebene. Die Bedeutung von outerradius, innerradius, slices und rings ist wie für eine vollständige Scheibe. Es wird aber nur der Ausschnitt von startangle bis startangle+sweepangle gezeichnet (beide Winkel in Grad gemessen). Dabei bedeuten 0 die positive y-achse, 90 die positive x-achse usw. Orientierung und Texturkoordinaten sind wie bei der vollständigen Scheibe. Die Kenngrößen von Quadriken sollte man direkt über die Parameter einstellen statt sie mit gl.glscale() zu verändern, denn dann brauchen die Normalenvektoren nicht renormalisiert zu werden. Außerdem sollten die Unterteilungsparameter deutlich größer als Eins gesetzt werden, um eine feinere Beleuchtungsrechnung zu erzwingen, besonders bei stark spiegelnden Materialien. 8.3 Attributverwaltung Schließlich können noch die Zeichenattribute von Quadriken eingestellt werden. Dazu gibt es die folgenden Funktionen (die natürlich jeweils vor dem eigentlichen Zeichnen aufzurufen sind). Sie werden im nächsten Beispiel verwendet. 21

22 Die Funktion void glu.gluquadricdrawstyle (GLUquadric quad, int drawstyle); spezifiziert über drawstyle die Darstellungsart. Folgende Werte sind zulässig. GLU.GLU_POINT und GLU.GLU_LINE: Darstellung durch einen Punkt ein jeder Ecke bzw. durch eine Strecke zwischen je zwei Ecken. GLU.GLU_SILHOUETTE: Darstellung durch Strecken unter Weglassen von Kanten zwischen koplanaren Flächen. Dies wird am häufigsten für (partielle) Scheiben verwendet. GLU.GLU_FILL: Darstellung durch gefüllte Polygone, die bezüglich ihrer Normalen im Gegenuhrzeigersinn orientiert sind. Die Orientierung kann mit der nachfolgenden Funktion geändert werden. Die Funktion void glu.gluquadricorientation (GLUquadric quad, int orientation); gibt die Orientierung der Normalen von quad ein. Per Voreinstellung ist sie GLU.GLU_OUTSIDE; sie kann zu GLU.GLU_INSIDE umgestellt werden. Die Funktion void glu.gluquadricnormals (GLUquadric quad, int normals); stellt ein, wann Normalen erzeugt werden sollen. Bei GLU.GLU_NONE (der Voreinstellung) werden keine Normalen erzeugt; dieser Modus ist nur interessant, wenn ohne Beleuchtung gearbeitet wird. Bei GLU.GLU_FLAT wird für jede Fläche nur eine Normale erzeugt; dieser Modus ist für Flächenschattierung geeignet. Bei GLU.GLU_SMOOTH wird für jede Ecke einer Fläche die Eckennormale erzeugt; dieser Modus ist für Gouraudschattierung geeignet. Die Funktion void glu.gluquadrictexture (GLUquadric quad, boolean texturcoords); stellt ein, ob für quad Texturkoordinaten erzeugt werden sollen. Die Voreinstellung ist GL.GL_FALSE, die Alternative GL.GL_TRUE. 22

23 9 Beleuchtung Im folgenden werden wir mit gl immer eine Instanz der Klasse GL bezeichnen. JOGL erlaubt die Verwaltung von mindestens acht Lichtquellen (unter den Bezeichnungen GL_LIGHT0 bis GL_LIGHTi mit i = GL_MAX_LIGHTS). Für jede muss folgendes angegeben werden: die Position, die Farbe, die Abhängigkeit der Intensität von der Entfernung, der Typ (ambient, diffus, spiegelnd (specular)). Damit Lichter definiert werden können, ist mit gl.glenable(gl_lighting) die Beleuchtungsrechnung zu aktivieren. Nach Definition eines Lichts GL.GL_LIGHTi muss es mit gl.glenable(gl.gl_lighti) eingeschaltet werden. Per Voreinstellung hat jedes Licht die Farbe Weiß und die Position (0, 0, 1). Andere Einstellungen wählt man mit void gl.gllightfv (int light, int pname, float[] params, int params_offset) Dabei sind folgende Werte für paramname möglich: 23

24 Parameter setzt Voreinstellung GL.GL_AMBIENT ambiente Lichtfarbe (0.0, 0.0, 0.0, 1.0) GL.GL_DIFFUSE diffuse Lichtfarbe (1.0, 1.0, 1.0, 1.0) GL.GL_SPECULAR spiegelnde Lichtfarbe (1.0, 1.0, 1.0, 1.0) GL.GL_POSITION Position in homogenen (0.0, 0.0, 1.0, 0.0) Koordinaten; w = 0.0 bedeutet ein Licht im Unendlichen (Richtungslicht in Richtung (x, y, z)) GL.GL_SPOT_DIRECTION Richtung eines Spots (0.0, 0.0, 1.0) GL.GL_SPOT_EXPONENT Exponent eines Spots 0.0 (siehe Phong-Modell) GL.GL_SPOT_CUTOFF halber Öffnungswinkel 180 in [0, 90 ] {180 (d. h. gar kein Spot) GL.GL_CONSTANT Abschwächung mit der 1.0 _ATTENUATION Entfernung GL.GL_LINEAR Abschwächung mit der 0.0 _ATTENUATION Entfernung GL.GL_QUADRATIC Abschwächung mit der 0.0 _ATTENUATION Entfernung Schließlich können noch die Materialeigenschaften von Oberflächen eingestellt werden mit void gl.glmaterialfv(int face, int pname, float[] params, int params_offset); Dabei bestimmt face {GL.GL_FRONT, GL.GL_BACK, GL.GL_FRONT_AND_BACK, welche Seite eines Polygons von der Materialdefinition betroffen ist. Für paramname gilt folgendes: Parameter setzt Voreinstellung GL.GL_AMBIENT ambiente Farbe (0.2, 0.2, 0.2, 1.0) GL.GL_DIFFUSE diffuse Farbe (0.8, 0.8, 0.8, 1.0) GL_SPECULAR spiegelnde Farbe (0.0, 0.0, 0.0, 1.0) GL.GL_EMISSION emittierte Farbe (0.0, 0.0, 0.0, 1.0) GL.GL_SHININESS Spiegelungsexponent 0.0 Manchmal möchte man für ausgewählte Materialparameter die aktuelle Zeichenfarbe übernehmen. Hierzu dient: void gl.glcolormaterial(int face, int mode) Für face bzw. mode sind die gleichen Werte zulässig wie für face bzw. paramname in glmaterialfv. Die Voreinstellungen sind GL.GL_FRONT_AND_BACK 24

25 bzw. GL.GL_AMBIENT_AND_DIFFUSE. Die Möglichkeit, diese Funktion auszuführen, wird mit gl.glenable/gl.gldisable (GL.GL_COLOR_MATERIAL) ein/ausgeschaltet. Damit die Beleuchtungsrechnung in JOGL richtig funktioniert, muss die Tiefenpufferung zur Behandlung verdeckter Flächen eingeschaltet sein. JOGL übernimmt nur die lokale Beleuchtungsanalyse; globale Analyse muss der Benutzer i. W. selbst programmieren. Allerdings kann zumindest ein globales Licht angegeben werden mittels void gl.gllightmodelfv(int pname, float[] params, int params_offset) Parameter setzt Voreinstellung GL.GL_LIGHT_MODEL globales ambientes Licht (0.2, 0.2, 0.2, 1.0) _AMBIENT GL.GL_LIGHT_MODEL _LOCAL_VIEWER Berechnungsart für Reflexion: bei Wert 0.0 wird v in negativer z-richtung genommen, unabhängig von der echten 0.0 GL.GL_LIGHT_MODEL _TWO_SIDE Betrachterposition. ein- oder zweiseitige Beleuchtungsberechnung für Polygone (0.0 = einseitig). Eckpunkte werden stets nach den Materialparametern der Vorderseite gefärbt Globales Licht hat den Nachteil, dass es nicht ausgeschaltet werden kann, während einzelne Lichter jederzeit an- oder ausgeschaltet werden können. Zu beachten ist, dass Lichtquellen stets der aktuellen Modelltransformation unterworfen werden. Schließlich wollen wir noch die Erzeugung von Nebeleffekten besprechen. Sie wird ein/ausgeschaltet mit gl.glenable/gl.gldisable(gl.gl_fog). Zur Definition der Nebelart dienen void gl.glfogfv(int pname, float[] params, int params_offset) void gl.glfogf(int pname, float param) Die Nebelberechnung geht so: Wie stark die tatsächliche Farbe eines Objekts vom Nebel abgedämpft und verändert wird, bestimmt sich durch die Koordinate z des Objekts im Kamerakoordinatensystem und einen von z abhängigen Nebelfaktor f(z) [0, 1]. Ist c o die eigentliche Objektfarbe und c n die Nebelfarbe, so ergibt sich die vernebelte Farbe als c on (z) = f(z) c o + (1 f(z)) c n. Am realistischsten wirkt der Nebel, wenn f(z) eine Exponentialfunktion f(z) = e dz mit der Nebeldichte d ist. Weiter verwendet man linearen Nebelverlauf,

26 f(z) = z e z a z e z a, wobei z a den Anfang und z e das Ende des Nebelbereichs bedeutet, sowie die Gauß-Verteilung (auch doppelt exponentielle Verteilung genannt) Die JOGL-Parameter dazu folgen. f(z) = e dz2. pname params/param Voreinstellung GL.GL_FOG_MODE Nebelfaktor f(z) GL.GL_EXP GL.GL_LINEAR, GL.GL_EXP, GL.GL_EXP2 GL.GL_FOG_DENSITY Nebeldichte d 1.0 GL.GL_FOG_START z a 0.0 GL.GL_FOG_END z e 1.0 GL.GL_FOG_COLOR Nebelfarbe c n Die Qualität der Nebelberechnung kann noch mit void gl.glhint(int target, int mode) beeinflusst werden. Als target ist GL.GL_FOG_HINT zu wählen, für mode {GL.GL_FASTEST, GL.GL_NICEST, GL.GL_DONT_CARE ergibt sich niedrigste, höchste, bzw. systemabhängige Qualität. 10 Texturen 10.1 Erste Beispiele Zunächst werden zwei Bilddateien auf zwei Quadrate aufgebracht. Das eine wird in Frontalansicht, das andere um 45 nach hinten gedreht gezeigt. In Objektkoordinaten sind beide Quadrate gleich groß; die Textur wird im zweiten Fall perspektivisch mitverzerrt. Wir geben nur die relevanten Programmteile an. import java.io.*; // zur Behandlung von Bilddateien als Texturen... import com.sun.opengl.util.texture.*;... public class Beispiel_Text3 { static class WinRenderer extends GLCanvas implements GLEventListener 26

27 { private GLU glu = new GLU(); private Texture tex0,tex1; private Texture tex0,tex1; private Texture loadtexture(string fnm){ String filename = fnm; Texture tex = null; try { tex = TextureIO.newTexture( new File(fileName), false); tex.settexparameteri(gl.gl_texture_mag_filter, GL.GL_NEAREST); tex.settexparameteri(gl.gl_texture_min_filter, GL.GL_NEAREST); catch(exception e) { System.out.println("Error loading texture " + filename); return tex; public void display(glautodrawable gldrawable){ GL gl = gldrawable.getgl(); gl.glclear(gl.gl_color_buffer_bit GL.GL_DEPTH_BUFFER_BIT); gl.glloadidentity(); //glu.glulookat(0,0,0.5,0,0,0,0,1,0); glu.glulookat(2,0,4,0,0,0,0,-1,0); gl.glenable(gl.gl_texture_2d); gl.gltexenvf(gl.gl_texture_env, GL.GL_TEXTURE_ENV_MODE, GL.GL_DECAL); tex0.bind(); gl.glbegin(gl.gl_quads); gl.gltexcoord2f(0.0f, 0.0f); gl.glvertex3f(-2.0f, -1.0f, 0.0f); gl.gltexcoord2f(0.0f, 1.0f); gl.glvertex3f(-2.0f, 1.0f, 0.0f); gl.gltexcoord2f(1.0f, 1.0f); gl.glvertex3f(0.0f, 1.0f, 0.0f); gl.gltexcoord2f(1.0f, 0.0f); gl.glvertex3f(0.0f, -1.0f, 0.0f); gl.glend(); tex1.bind(); gl.glbegin(gl.gl_quads); gl.gltexcoord2f(0.0f, 0.0f); gl.glvertex3f(1.0f, -1.0f, 0.0f); gl.gltexcoord2f(0.0f, 1.0f); 27

28 gl.glvertex3f(1.0f, 1.0f, 0.0f); gl.gltexcoord2f(1.0f, 1.0f); gl.glvertex3f( f, 1.0f, f); gl.gltexcoord2f(1.0f, 0.0f); gl.glvertex3f( f, -1.0f, f); gl.glend(); gl.glflush(); gl.gldisable(gl.gl_texture_2d); public void init(glautodrawable gldrawable){ GL gl = gldrawable.getgl(); gl.glclearcolor (0, 0, 0, 0); gl.glshademodel(gl.gl_flat); gl.glenable(gl.gl_depth_test); tex0 = loadtexture("pnglogo.png"); tex1 = loadtexture("ausflugschnitt.jpg"); Die Initialisierung für das Texturieren erfolgt in init(), indem die beiden Bilder in Texturen umgewandelt werden. Die Aufrufe von gl.gltexparameter*() in loadtexture spezifizieren, wie die Textur umgebrochen wird und wie die Farben gefiltert werden, wenn die Texel und Pixel nicht zusammenpassen. In display() schaltet gl.glenable() die Texturierung ein. gl.gltexenv*() setzt die Zeichenart auf GL.GL_DECAL ( Abziehbild ), so daß die texturierten Polygone die Farben der Textur statt ihrer Originalfarbe bekommen. Dann werden die beiden Quadrate gezeichnet. Der Aufruf von bind() bedeutet, dass ab dort die jeweilige Textur verwendet wird, solange bis eine andere gebunden wird. Man beachte, daß die Texturkoordinaten zusammen mit den Punktkoordinaten spezifiziert werden. Der Aufruf gl.gltexcoord*() setzt die aktuellen Texturkoordinaten; alle nachfolgend definierten Punkte bekommen diese Texturkoordinaten, bis gl.gltexcoord*() nochmals aufgerufen wird. Achtung: Wird das Bild nicht korrekt angezeigt, kann ein Aufruf der Form gl.glhint(gl.gl_perspective_correction_hint,gl.gl_nicest) helfen. Im zweiten Beispiel werden keine externen Bilder verwendet, sondern zwei vergleichsweise kleine Schachbretttexturen erzeugt und aufgebracht. 28

29 ... /* Erzeuge Schachbrettmuster */ private BufferedImage drawcheckerboard (int bsize, int xsquares, int ysquares){ int w = bsize, h = bsize; BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics g = img.getgraphics(); int x = 0, y = 0; Color c1 = Color.blue; Color c2 = Color.red; double squarewidth = (double)w / xsquares; double squareheight = (double)h / ysquares; // Fill background color g.setcolor(c1); g.fillrect(0,0,w,h); // Draw squares g.setcolor(c2); for(int row = 0; row < ysquares; row++){ for(int col = 0; col < xsquares; col++){ if((row + col) % 2 == 0){ x = (int)(row * squareheight); y = (int)(col * squarewidth); g.fillrect(x,y,(int)squarewidth, (int)squareheight); return img; public void init(glautodrawable gldrawable){ GL gl = gldrawable.getgl(); gl.glclearcolor (0, 0, 0, 0); gl.glshademodel(gl.gl_flat); gl.glenable(gl.gl_depth_test); // erzeuge Texturen aus Pufferbildern BufferedImage img0,img1; img0 = drawcheckerboard(128,10,10); tex0 = TextureIO.newTexture(img0,false); 29

30 img1 = drawcheckerboard(64,5,5); tex1 = TextureIO.newTexture(img1,false); Texturobjekte Ein Texturobjekt speichert Texturdaten und macht sie leicht verfügbar. Man kann damit mehrere Texturen verwalten und zu früher geladenen Texturen zurückkehren. Benutzung von Texturobjekten ist meist die effizienteste Art, Texturen zu verwenden, weil es fast immer schneller ist, ein existierendes Texturobjekt zu binden (d.h. wiederzuverwenden), als eine Textur nochmals zu laden. Zusätzlich unterstützen einige Implementierungen einen begrenzten Satz von residenten, besonders schnell benutzbaren Texturen (vgl. Abschnitt??). Mit Texturobjekten kann man seine am häufigsten benutzten Texturen in diesen Satz einfügen. Um Texturobjekte zu verwenden, sind folgende Schritte nötig. Erzeuge Texturnamen. Erzeuge Texturobjekte und binde sie erstmals an Texturdaten, einschließlich der Bitmap und der Textureigenschaften. Unterstützt die Implementierung residente Texturen, so prüfe, ob der Speicher für alle Texturobjekte ausreicht. Wenn nicht, definiere Prioritäten für die Texturobjekte, so daß häufiger verwendete resident bleiben. Binde Texturobjekte erstmalig oder erneut und mache damit ihre Daten für das eigentliche Texturieren verfügbar Benennung von Texturobjekten Jede vorzeichenlose positive Ganzzahl kann als Texturname dienen. Um Namenskonflikte zu vermeiden, sollte man Texturnamen konsistent nur über gl.glgentextures() erzeugen. Die Funktion void gl.glgentextures (int n, int[] texnames, int offset) liefert n momentan unbenutzte Namen für Texturobjekte im Feld texnames ab; sie müssen kein zusammenhängendes Intervall bilden. Die Namen werden als belegt markiert, aber sie erhalten Texturstatus und -dimensionalität (1D oder 2D) erst, wenn sie erstmals gebunden werden. Der Parameter offset gibt an, ab welcher Indexposition das erzeugte Feld relevant ist. 30

31 Der Texturname 0 ist reserviert und wird nie als Ergebnis von gl.glgentextures() geliefert. Die Funktion boolean gl.glistexture (int texname) prüft, ob texname momentan belegt ist. Wurde texname bereits von gl.glgentextures() geliefert, aber noch nicht gebunden, liefert der Aufruf gl.glistexture(texname) das Ergebnis false Erzeugung und Verwendung von Texturobjekten Ein und die selbe Funktion, nämlich void gl.glbindtexture (int target, int texname), erzeugt und verwendet Texturobjekte. Wird der texname zum ersten Mal gebunden, wird ein neues Texturobjekt erzeugt mit Voreinstellungen für die Textur und Textureigenschaften. Weitere Aufrufe von gl.glteximage, gl.gltexsubimage, gl.glcopyteximage, gl.glcopytexsubimage, gl.gltexparameter und gl.glprioritizetextures speichern dann Daten in diesem Texturobjekt. Neben einer Textur und zugehörigen Mipmaps können das etwa Breite, Höhe, Randbreite, Internformat, Auflösung von Komponenten und Textureigenschaften sein; letztere umfassen Filter für Minification und Magnification, Wiederholungsmodi, Randfarbe und Priorität. Wird das Texturobjekt später erneut gebunden, erhält es als Daten den aktuellen Texturzustand, sein früherer Wert wird überschrieben. Außerdem wird es damit aktiv. Wird als texname der Wert 0 übergeben, beendet JOGL die Verwendung von Texturobjekten und greift auf eine unbenannte Standardtextur zurück. Der Inhalt des momentan gebundenen Texturobjekts kann auch verändert werden; damit ändern sich auch die entsprechenden Teile des aktuellen Texturzustands. Im vorigen Beispiel ist man nach Beendigung von display() immer noch an die Textur gebunden, die Inhalt von texname[1] ist. Man muss also darauf achten, daß man nicht durch einen Aufruf einer Texturfunktion ungewollt die Daten in der aktuellen Textur verändert. Alle zu einer Textur gehörigen Mipmaps müssen in einem einzigen Texturobjekt abgelegt werden (siehe das Beispiel in Abschnitt??). Mit glpixelstorei(gl_unpack_alignment,1) kann man beim Erstellen einer Textur, wenn nötig, die Texturdaten am Ende jeder Texturzeile ausrichten. 31

32 Entsorgen von Texturobjekten Um die Systemressourcen zu schonen, sollte man Texturen wieder freigeben, wenn sie nicht mehr benötigt werden. Die Funktion void gl.gldeletetextures (int n, int[] texnames, int offset) löscht n Texturobjekte, die im Feld texnames von offset an genannt sind. Sie können dann (z.b. von gl.glgentextures()) wiederverwendet werden. Wird eine momentan gebundene Textur freigegeben, ist die Wirkung wie bei einem Aufruf gl.glbindtexture(0). Versuche, unbelegte Texturnamen oder 0 freizugeben, werden ohne Fehlermeldung ignoriert Texturspezifikation Die Funktion void gl.glteximage2d (int target, int level, int internalformat, int width, int height, int border, int Format, int type, Buffer pixels); definiert eine 2D-Textur; die analoge für 1D-Texturen ist gl.glteximage1d(). Wir beschreiben hier ihre wichtigsten Parameter; die weiteren werden in späteren Abschnitten behandelt. target kann die Werte GL.GL_TEXTURE_2D oder GL.GL_PROXY_TEXTURE_2D (siehe Abschnitt??) annehmen. Der Parameter level wird verwendet, wenn die Textur verschiedene Auflösungen haben soll; bei nur einer Auflösung sollte level = 0 sein (Genaueres später). Der Parameter internalformat gibt an, welche der RGBA-, Luminanz- oder Intensitätswerte für die Texel eines Bildes verwendet werden. internalformat ist eine Ganzzahl von 1 bis 4 oder eine von 38 symbolischen Konstanten (siehe den Abschnitt Texturfunktionen für Details), die auch für internalformat zulässig sind. Sie lauten GL.GL_ALPHA, GL.GL_ALPHA4, GL.GL_ALPHA8, GL.GL_ALPHA12, Gl.GL_ALPHA16, Gl.GL_LUMINANCE, Gl.GL_LUMINANCE4, GL.GL_LUMINANCE8, Gl.GL_LUMINANCE12, Gl.GL_LUMINANCE16, Gl.GL_LUMINANCE_ALPHA, GL.GL_LUMINANCE4_ALPHA4, GL.GL_LUMINANCE6_ALPHA2, GL.GL_LUMINANCE8_ALPHA8, GL.GL_LUMINANCE12_ALPHA4, GL.GL_LUMINANCE12_ALPHA12, GL.GL_LUMINANCE16_ALPHA16, GL.GL_INTENSITY, GL.GL_INTENSITY4, GL.GL_INTENSITY8, GL.GL_INTENSITY12, GL.GL_INTENSITY16, GL.GL_RGB, GL.GL_R3_G3_B2, GL.GL_RGB4, GL.GL_RGB5, GL.GL_RGB8, 32

33 GL.GL_RGB10, GL.GL_RGB12, GL.GL_RGB16, GL.GL_RGBA, GL.GL_RGBA2, GL.GL_RGBA4, GL.GL_RGB5_A1, GL.GL_RGBA8, GL.GL_RGB10_A2, GL.GL_RGBA16. Mit diesen Konstanten stellt man spezifische Komponenten und ggf. deren Auflösung ein. Z.B. bedeutet internalformat = GL.GL_R3_G3_B2 den Wunsch, daß in den Texelwerten 3 Bit für die Rot-, 3 Bit für die Grün- und 2 Bit für die Blauinformation dienen sollen. JOGL garantiert das aber nicht, sondern ist nur verpflichtet, eine Interndarstellung zu wählen, die solchen Wünschen nahekommt. GL.GL_LUMINANCE, GL.GL_LUMINANCE_ALPHA, GL.GL_RGB und GL.GL_RGBA sind per Definition nachsichtig, weil sie keine spezifische Auflösung verlangen. Die Parameter width und height geben die Dimensionen der Textur an; border spezifiziert den Rand (0 = kein Rand, 1 = Rand). Höhe und Breite müssen die Form 2m + 2b haben, wobei m eine nicht-negative Ganzzahl ist (kann für Höhe und Breite unterschiedlich sein) und b der Wert von border. Die Maximalgröße einer Textur hängt von der Implementierung von JOGL ab, muss aber mindestens (oder mit Rand) sein. Der Parameter Format hat als mögliche Werte GL.GL_COLOR_INDEX, Gl.GL_RGB, GL.GL_RGBA, GL.GL_RED, GL.GL_GREEN, GL_BLUE, GL.GL_ALPHA, GL_LUMINANCE, GL.GL_LUMINANCE_ALPHA. Für type sind zulässig GL.GL_BYTE, GL.GL_UNSIGNED_BYTE, GL.GL_SHORT, GL_UNSIGNED_SHORT, GL.GL_INT, GL.GL_UNSIGNED_INT, GL.GL_FLOAT, GL.GL_BITMAP. Schließlich enthält pixels die eigentlichen Texturdaten, und zwar für Inneres und Rand des Bilds. Dabei ist Buffer eine abstrakte Oberklasse für die implementierungsnahen Klassen ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer und ShortBuffer. Das interne Format einer Textur kann die Effizienz von Texturoperationen beeinflussen. Z.B. ist in einigen Implementierungen Texturierung mit GL.GL_RGBA schneller als mit GL.GL_RGB, weil die Farbkomponenten den Speicher besser ausnutzen. Man sollte daher die Spezifika der jeweiligen Implementierung von JOGL prüfen. Vom internen Format einer Textur kann auch abhängen, wieviel Speicher sie benötigt. Z.B. braucht eine Textur mit internem Format GL.GL_RGBA8 32 Bit pro Texel, eine mit internem Format GL.GL_R3_G3_B2 nur 8 Bit pro Texel. Natürlich hat man einen Abtausch zwischen Speicherverbrauch und Farbauflösung. 33

34 Die Anzahl von Texeln für Breite und Höhe einer Textur (ohne Rand) muss jeweils eine Zweierpotenz sein. Hat das Originalbild andere Dimensionen, kann man sie mit int glu.gluscaleimage (int Format, int widthin, int heightin, int typein, Buffer datain, int widthout, int heightout, int typeout, Buffer dataout); ändern. Die Parameter Format, typein und typeout verhalten sich wie bei gl.gldrawpixels(). Das Bild wird mittels linearer Interpolation und Box- Filterung skaliert (von der Größe widthin und heightin auf widthout und heightout) und das resultierende Bild nach dataout gespeichert und zwar im GL.GL_PACK*-Speichermodus für Pixel. Der Aufrufer von glu.gluscaleimage() muss genügend Platz für den Ausgabepuffer reservieren. Bei Erfolg ist der Rückgabewert 0; ansonsten wird ein GLU-Fehlercode abgeliefert. Auch der Bildpuffer selbst kann als Quelle für Texturen dienen. Die Funktion void gl.glcopyteximage2d (int target, int level, int internalformat, int x, int y, int width, int height, int border) liest ein Rechteck von Pixeln aus dem aktuellen GL.GL_READ_BUFFER und verwendet es für eine neue Textur. Die Pixel werden wie mit gl.glcopypixels() verarbeitet, bis auf die Konversion am Ende. Dabei werden die Einstellungen von gl.glpixeltransfer*() angewendet. Der Parameter target muss den Wert GL.GL_TEXTURE_2D haben. Die Parameter level, internalformat und border haben die selben Effekte wie bei gl.glteximage2d(). Das Texturfeld hat seine linke untere Ecke bei den Pixelkoordinaten(x, y). width und height spezifizieren die Größe. Sie müssen, wie oben, die Form 2m + 2b haben Die Klassen TextureData und TextureIO Sehr mächtige Hilfsmittel, die die Verwendung von Texturen stark vereinfachen, sind die Klassen TextureData und TextureIO. Wir gehen hier nicht auf alle Details ein; der interssierte Leser kann sich unter schlau machen Die Klasse TextureIO Diese Klasse stellt ein riesiges Arsenal von Methoden zum Einlesen und Erzeugen von Texturen zur Verfügung. Wir stellen nun einige vor: 34

35 Texture TextureIO.newTexture (BufferedImage image, boolean mipmap) erzeugt ein neues Texturobjekt aus dem angegebenen BufferedImage mit oder ohne MipMapping entsprechend dem mipmap-parameter Texture TextureIO.newTexture (File file, boolean mipmap) erzeugt ein neues Texturobjekt aus dem spezifizierten File mit oder ohne Mip- Mapping entsprechend dem mipmap-parameter Texture TextureIO.newTexture (TextureData data) erzeugt ein neues Texturobjekt aus dem angegeben TextureData-Objekt (siehe nächster Abschnitt) Texture TextureIO.newTexture (URL url, boolean mipmap, String filesuffix) erzeugt ein neues Texturobjekt aus dem angegebenen URL mit oder ohne Mip- Mapping entsprechend dem mipmap-parameter. filesuffix gibt einen Hinweis auf das Format, in dem die Ressource vorliegt, z.b..jpg oder.gif. Hat dieser Parameter den Wert null, so wird eine automatische Erkennung versucht Die Klasse TextureData Die Klasse TextureData beinhaltet Informationen über eine Textur. Laut API wurde sie von der Texture-Klasse getrennt, zum Beispiel die Verwendung von Texture-Streams in Hintergrundthreads ohne OpenGL/JOGL-Kontext zu ermöglichen. Der einfachste Konstruktor hat die Form new TextureData(int internalformat, int pixelformat, boolean mipmap, BufferedImage image) Die Parameter internalformat und pixelformat geben das interne Format für die entstehende Textur an; man kann ihnen auch den Wert 0 geben, wobei dann das interne Format vom Bildtyp abgeleitet wird. Skurillerweise wird der pixelformat-parameter gegenwärtig ignoriert. mipmap gibt an, ob automatisch mipmaps erzeigt werden sollen, während image eine kanonische Bedeutung hat. 35

36 Aus einem solchen TextureData-Objekt kann man nun die verschiedenen Eigenschaften mittels get-methoden abfragen, so liefert zum Beispiel int TextureData.getHeight() die Höhe in Pixeln. Mit set-methoden kann man dann die Eigenschaften auch setzen, z.b. void TextureData.setHeight(int height) Ersetzen von (Teil-)Texturen Eine Textur neu zu erzeugen kann aufwendiger sein, als eine existierende zu modifizieren. JOGL bietet Funktionen zum Ersetzen von (Teilen von) Texturen durch neue Information. Das ist z.b. bei Verwendung von Echtzeit- Videobildern als Texturen vorteilhaft. Dazu erzeugt man eine Textur mit gl.gltexsubimage2d(), um die Texturdaten wiederholt durch die neuen Videobilder zu ersetzen. Außerdem haben die Teilbilder für gl.gltexsubimage2d() nicht die Beschränkung, daß Breite und Höhe Zweierpotenzen sein müssen, die von Videobildern meist nicht erfüllt wird. Die Funktion void gl.gltexsubimage2d (int target, int level, int xoffset, int yoffset, int width, int height, int Format, int type, Buffer pixels) definiert eine 2D-Textur, die ein zusammenhängendes Teilgebiet (in 2D ein Rechteck) der aktuellen 2D-Textur ersetzt. Der Parameter target muss auf GL.GL_TEXTURE_2D gesetzt werden. Die Parameter level, Format und type sind analog zu denen für gl.glteximage2d(). level gibt das Detailniveau für das Mipmapping (vgl. Abschnitt??) an. Es ist zwar kein Fehler, eine Breite oder Höhe von 0 zu spezifizieren, aber das Teilbild hat dann keinen Effekt. Format und type sind selbsterklärend. Das Teilbild wird auch von den Modi betroffen, die in gl.glpixelstore*() und gl.glpixeltransfer*() gesetzt werden. pixels enthält die Texturdaten für das Teilbild. width und height sind die Dimensionen des Gebiets, das einen Teil der aktuellen Textur ersetzt. xoffset und yoffset spezifizieren, wo die Teiltextur angebracht wird (mit (0, 0) als linker unterer Ecke der Textur). Dabei darf man den Bereich der Originaltextur nicht verlassen. Auch hier kann der Bildpuffer selbst als Quelle für Texturdaten dienen, und zwar für eine Teiltextur. gl.glcopytexsubimage2d() liest ein Rechteck von Pixeln aus dem Bildpuffer und ersetzt einen Teil einer vorhandenen Textur. (gl.glcopytexsubimage2d() ist eine Art Kreuzung aus gl.glcopyteximage2d() und gl.gltexsubimage2d().) 36

37 Die Funktion void gl.glcopytexsubimage2d (int target, int level, int xoffset, int yoffset, int x, int y, int width, int height) benützt Daten aus dem Bildpuffer, um ein zusammenhängendes Teilgebiet der aktuellen 2D-Textur zu ersetzen. Die Pixel werden aus dem aktuellen GL.GL_READ_BUFFER gelesen und genau wie bei einem Aufruf von gl.glcopypixels() verarbeitet, wieder ohne die Schlußkonversion. Dabei werden die Einstellungen von gl.glpixelstore*() und gl.glpixeltransfer*() verwendet. Der Parameter target muss auf GL.GL_TEXTURE_2D gesetzt werden. level ist wieder das Mipmap-Detailniveau. xoffset und yoffset spezifizieren, wo die Teiltextur angebracht wird, width und height die Größe des Teilbilds. Ein anderer Weg wird im Beispiel TeilText2.java beschritten: Hier wird updatesubimage-methode der Texture-Klasse verwendet. Sie überschreibt eine Textur in einem spezifizierten Bereich mit einem neuen Bild. Ihre einfachere Signatur ist void Texture.updateSubImage (TextureData data, int mipmaplevel, int x, int y) data ist das TextureData-Objekt, mit dem (besser gesagt, mitt dessen zugehöriger Textur) die alte Textur überschrieben werden soll. mipmaplevel gibt an, welche mipmap-ebene der Textur überschrieben werden soll. x und y beschreiben den Ort der linken unteren Ecke der überschreibenden neuen Textur, gerechnet in Pixeln von der linken unteren Ecke der alten Textur aus D-Texturen Manchmal reicht eine 1D-Textur aus z.b. wenn man texturierte Bänder zeichnet, wobei sich das Muster nur in einer Richtung ändert. Eine 1D-Textur verhält sich wie eine 2D-Textur der Höhe 1 und ohne Ränder oben und unten. Zu allen 2D-Textur- und Teiltexturfunktionen gibt es 1D-Gegenstücke. Um eine einfache 1D-Textur zu erzeugen benützt man void gl.glteximage1d (int target, int level, int internalformat, int width, int border, int Format, int type, Buffer pixels) 37

38 Die Parameter haben die selbe Bedeutung wie für gl.glteximage2d(), außer daß das Bild nun ein 1D-Feld von Texeln ist. Wie zuvor muss die Breite 2m (oder 2m + 2, wenn ein Rand vorliegt) mit einer nicht-negativen Ganzzahl m sein. Auch Mipmaps, Proxies (mit target = GL.GL_PROXY_TEXTURE_1D) und die selben Filteroptionen sind verfügbar. Für ein Beispiel mit einer 1D-Textur siehe Abschnitt??. Um alle oder einige Texel einer 1D-Textur zu ersetzen, verwendet man void gl.gltexsubimage1d (int target, int level, int xoffset, int width, int Format, int type, Buffer pixels) Der Parameter target muss auf GL.GL_TEXTURE_1D gesetzt sein. Die übrigen Parameter sind analog denen für gl.glteximage1d(). Um den Bildpuffer als Quelle einer neuen oder Ersatz-1D-Textur zu nehmen, verwendet man void gl.glcopyteximage1d (int target, int level, int internalformat, int x, int y, int width, int border) void gl.glcopytexsubimage1d (int target, int level, int xoffset, int x, int y, int width) 10.7 Ränder Will man eine größere Textur verwenden als die gegebene Implementierung von JOGL erlaubt, kann man mit etwas Vorsicht größere Texturen aus Kacheln mit kleineren Texturen zusammensetzen. Braucht man z.b. eine doppelt so große Textur als erlaubt auf einem Quadrat, zeichnet man das Quadrat als vier Teilquadrate und lädt jedes Mal eine andere Textur bevor man das nächste Stück zeichnet. Weil zu jedem Zeitpunkt nur eine einzige Textur verfügbar ist, kann das an den Texturkanten zu Problemen führen, besonders bei linearer Filterung. Die Texturwerte für Pixel an den Rändern müssen mit Werten jenseits der Kante abgeglichen werden, die idealerweise aus der Nachbartextur stammen sollten. In diesem Fall sollte man einen Texturrand definieren, dessen Texelwerte mit denen am Rand der Nachbartextur übereinstimmen. Dabei ist zu beachten, daß eine Textur bis zu acht Nachbarn haben kann (vier an den Seiten und vier an den Ecken). Für Texturen, die selbst am Rand des Gesamtgebiets aufgebracht werden, muss man überlegen, welche Randwerte sinnvoll sind. 38

39 10.8 Detailniveaus (Mipmaps) JOGL unterstützt Mipmaps und berechnet automatisch, welche Textur gemäß der Pixelgröße des texturierten Objekts gewählt werden muss. Mipmaps erfordern zwar einigen Rechen- und Speicheraufwand; ohne sie könnten aber Texturen, die auf zu kleine Objekte aufgebracht werden, flackern oder blitzen, wenn sich die Objekte bewegen. Mipmaps funktionieren in JOGL nur, wenn die Texturen für alle Zweierpotenzen zwischen der größten benötigten Auflösung und 1 bereitgestellt werden. Ist z.b. die höchste Auflösung 64 16, muss man auch Texturen der Auflösungen 32 8, 16 4, 8 2, 4 1, 2 1 und 1 1 angeben. Die kleineren werden üblicherweise durch Filtern und Mittelwertbildung aus der größten erzeugt. Um diese Texturen auszuwählen, ruft man gl.glteximage2d() für jede Auflösung der Textur mit unterschiedlichen Werten für level, width, height und Bild auf. Beginnend mit 0 definiert level, welche Textur in der Folge gemeint ist; im vorigen Beispiel würde die größte Textur mit Auflösung durch level = 0 gewählt, die mit 32 8 durch level = 1 und so weiter. Damit die Mipmaps funktionieren, muss weiter eine der Filtermethoden aus Abschnitt?? verwendet werden. Das Beispiel MipMap.java zeigt die Verwendung einer Folge von sechs Mipmaps der Auflösungen bis 1 1. Das Programm zeichnet ein Rechteck, das sich vom Vordergrund bis weit in die Ferne erstreckt und schließlich ein einem Punkt verschwindet. Mit einem beliebigen Tastendruck lässt sich zwischen einer Texturierung mit und ohne MipMaping umschalten. JOGL enthält zwei Funktionen zur Erstellung von Mipmaps. Die Textur mit der höchsten Auflösung sei bereits erstellt. Dann erzeugen int glu.glubuild1dmipmaps (int target, int Komponenten, int width, int Format, int type, void *daten) int glu.glubuild2dmipmaps (int target, int Komponenten, int width, int height, int Format, int type, Buffer daten) die Pyramide von Mipmaps bis hinunter zur Auflösung 1 1 bzw. 1 (für 1D- Texturen). Sind die Dimensionen der Ausgangstextur keine Zweierpotenzen, skaliert glu.glubuild*dmipmaps() das Bild auf die nächstgelegene Zweierpotenz. Als Ergebnis wird 0 abgeliefert, wenn alle Mipmaps korrekt erzeugt werden konnten, ansonsten ein GLU-Fehlercode. 39

40 10.9 Filterung JOGL bietet eine Reihe von Filteroptionen mit unterschiedlichem Abtausch zwischen Schnelligkeit und Bildqualität. Dabei können die Filtermethoden für Magnification und Minification unabhängig gewählt werden. In einigen Fällen ist nicht klar, ob Magnification oder Minification nötig ist. Muß eine Mipmap sowohl in x- wie y-richtung gestreckt bzw. gestaucht werden, dann ist Magnification bzw. Minification zu verwendet. Wird sie aber in einer Richtung gestreckt und in der anderen gestaucht, trifft JOGL eine Auswahl zwischen Magnification und Minification, die in den meisten Fällen das bestmögliche Ergebnis liefert. Am besten ist es aber, solche Situationen zu vermeiden. Die folgenden Programmzeilen geben Beispiele, wie man gl.gltexparameter*() zum Spezifizieren von Magnification- und Minification- Filtermethoden verwendet: gl.gltexparameteri(gl.gl_texture_2d, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); gl.gltexparameteri(gl.gl_texture_2d, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); Das erste Argument von gl.gltexparameter*() ist entweder GL.GL_TEXTURE_2D oder GL.GL_TEXTURE_1D, je nachdem, ob man mit 2D- oder 1D-Texturen arbeitet. Für unsere Zwecke ist das zweite Argument entweder GL.GL_TEXTURE_MAG_FILTER oder GL.GL_TEXTURE_MIN_FILTER und gibt an, ob die Filtermethode für Magnification oder Minification spezifiziert wird. Das dritte Argument spezifiziert die Filtermethode; die nachfolgende Tabelle gibt die möglichen Werte an. Parameter Werte GL.GL_TEXTURE_MAG_FILTER GL.GL_NEAREST oder GL.GL_LINEAR GL.GL_TEXTURE_MIN_FILTER GL.GL_NEAREST, GL.GL_LINEAR, GL.GL_NEAREST_MIPMAP_NEAREST, GL.GL_NEAREST_MIPMAP_LINEAR, GL.GL_LINEAR_MIPMAP_NEAREST, GL.GL_LINEAR_MIPMAP_LINEAR Bei GL.GL_NEAREST wird das Texel mit Koordinaten am nächsten bei der Pixelmitte für Magnification und Minification herangezogen. Das kann zu (schlimmen) Treppeneffekten führen. Bei GL.GL_LINEAR wird eine Linearkombination des 2 2-Felds von Texeln am nächsten bei der Pixelmitte verwendet. Am Rand hängt es davon ab, ob GL.GL_REPEAT oder GL.GL_CLAMP eingestellt ist und ein Texturrand definiert ist. GL.GL_NEAREST ist weniger rechenaufwendig als GL.GL_LINEAR, aber GL.GL_LINEAR liefert glattere Ergebnisse. 40

41 Bei Magnification wird immer die größte Textur (level=0) verwendet, auch wenn Mipmaps definiert sind. Bei Minification kann man eine Filtermethode wählen, die die geeignetsten ein oder zwei Mipmaps verwendet. (Bei GL.GL_NEAREST oder GL.GL_LINEAR und Minification wird allerdings immer die größte Textur verwendet.) Wie in obiger Tabelle gezeigt, sind bei Minification von Mipmaps vier zusätzliche Filtermethoden verfügbar. Innerhalb einer einzelnen Mipmap wählt man die nächsten Texelwerte mit GL.GL_NEAREST_MIPMAP_NEAREST oder man interpoliert linear mit GL.GL_LINEAR_MIPMAP_NEAREST. Verwendung des nächsten Texels ist schneller, liefert aber weniger gute Ergebnisse. Welche spezielle Mipmap gewählt wird, hängt vom Betrag der Minification ab. Es gibt dazu jeweils Schwellenwerte, wann von einer Mipmap zur nächsten umgeschaltet wird. Plötzliche Übergänge werden durch die Werte GL.GL_NEAREST_MIPMAP_LINEAR oder GL.GL_LINEAR_MIPMAP_LINEAR vermieden; damit wird linear zwischen den Texelwerten der zwei besten Wahlmöglichkeiten interpoliert. GL.GL_NEAREST_MIPMAP_LINEAR wählt die nächstgelegenen Texel in beiden Mipmaps und interpoliert linear zwischen diesen zwei Werten. GL.GL_LINEAR_MIPMAP_LINEAR benützt lineare Interpolation, um die Werte in zwei Mipmaps zu berechnen, und interpoliert dann linear zwischen diesen zwei Werten. Erwartungsgemäß liefert im allgemeinen GL.GL_LINEAR_MIPMAP_LINEAR die glattesten Ergebnisse, ist aber am rechenaufwendigsten Texturfunktionen In allen bisherigen Beispielen wurden die Texturwerte direkt als Farben auf die texturierte Fläche aufgetragen. Man kann sie aber auch benutzen, um die Farbe der Fläche ohne Texturierung zu modulieren oder die Texturfarbe mit der Flächenfarbe zu mischen. Dazu verwendet man die Funktionen void gl.gltexenv{if(int target, int pname, TYPE param) void gl.gltexenv{ifv(int target, int pname, BTYPE param) Dabei steht TYPE für int bzw. float und BTYPE für IntBuffer bzw. FloatBuffer. Es gibt auch Überladungen mit Feld/Offset statt Bufferparametern. Schließlich muss target = GL.GL_TEXTURE_ENV sein. Hat pname den Wert GL.GL_TEXTURE_ENV_MODE, so hat param die möglichen Werte GL.GL_DECAL, GL.GL_REPLACE, GL.GL_MODULATE oder GL.GL_BLEND, die angeben, wie die Texturwerte mit den Flächenfarbwerten kombiniert werden. Hat pname den Wert GL.GL_TEXTURE_ENV_COLOR, so ist param ein Feld, das einen RGBA-Wert darstellt. Die Funktionen wirken nur, wenn GL.GL_BLEND eingestellt ist. 41

42 Die Kombination hängt auch vom Internformat ab, das als drittes Argument von gl.glteximage*d() angegeben werden muss. Dies ist in den nachfolgenden Tabellen dargestellt. Die sechs internen Grundformate sind GL.GL_ALPHA (A), Gl.GL_LUMINANCE (L), GL.GL_LUMINANCE_ALPHA (L und A), GL.GL_INTENSITY (I), GL.GL_RGB (C) und GL.GL_RGBA (C und A) (die Buchstaben in Klammern stehen für ihre Werte in den Tabellen). Weitere Internformate spezifizieren Auflösungen der Texturkomponenten und können auf eines dieser sechs internen Grundformate zurückgeführt werden. In den Tabellen bedeutet ein Index t einen Texturwert, f einen Flächenwert, c den über GL.GL_TEXTURE_ENV_COLOR zugewiesenen Wert; Größen ohne Index bezeichnen die schließlich errechneten Werte. internes Grundformat Ersetzungsfunktion Modulationsfunktion GL.GL_ALPHA C = C f, A = A t C = C f, A = A f A t GL.GL_LUMINANCE C = L t, A = A f C = C f L t, A = A f GL.GL_LUMINANCE_ALPHA C = L t, A = A t C = C f L t, A = A f A t GL.GL_INTENSITY C = E s, A = E s C = C f I t, A = A f I t GL.GL_RGB C = C t, A = A f C = C f C t, A = A f GL.GL_RGBA C = C t, A = A t C = C f C t, A = A f A t internes Grundformat Deckfunktion Mischfunktion GL.GL_ALPHA undefined C = C f A = A f A t GL.GL_LUMINANCE undefined C = C f (1 L t ) + C c L t A = A f GL.GL_LUMINANCE undefined C = C f (1 L t ) + C c L t _ALPHA A = A f A t GL.GL_INTENSITY undefined C = C f (1 E s ) + C c I t A = A f (1 E s ) + A c I t GL.GL_RGB C = C t, A = A f C = C f (1 C t ) + C c C t A = A f GL.GL_RGBA C = C f (1 A t ) + C t A t C = C f (1 C t ) + C c C t A = A f A = A f A t Die Deckfunktion wird verwendet, wenn eine undurchsichtige Textur auf ein Objekt aufgebracht werden soll; die Ersetzungsfunktion ist ähnlich. Ist bei Modulation das interne Grundformat GL.GL_INTENSITY, GL.GL_LUMINANCE oder GL.GL_LUMINANCE_ALPHA, so werden die Farbwerte mit den selben Werten multipliziert; damit moduliert die Textur zwischen der Flächenfarbe (wenn die Luminanz oder Intensität 1 ist) und schwarz (wenn sie 0 ist). Für die Internformate GL.GL_RGB und GL.GL_RGBA werden die Flächenfarbkomponenten mit entsprechenden (möglicherweise unterschiedlichen) Werten in der Textur multipliziert. Modulation ist im Zusammenhang mit Beleuchtung vorteilhaft, weil die beleuchtete Polygonfarbe benutzt werden kann, um die Texturfarbe abzuschwächen. Weiße spiegelnde Polygone werden 42

43 oft verwendet, um beleuchtete texturierte Objekte darzustellen, wobei die Textur die diffuse Farbe liefert. Die Mischfunktion ist die einzige, die die durch GL.GL_TEXTURE_ENV_COLOR spezifizierte Farbe verwendet. Deren Luminanz, Intensität oder Farbwert wird in etwa wie ein Alpha-Werte benutzt, um die Flächenfarbe mit GL.GL_TEXTURE_ENV_COLOR zu mischen. Genaueres hierzu später Zuweisen von Texturkoordinaten Texturkoordinaten können aus ein, zwei, drei oder vier Koordinaten bestehen, die meist s, t, r und q heißen um sie von den Objektkoordinaten x, y, z und w zu unterscheiden. Für 1D-Texturen benützt man nur s, für 2D-Texturen s und t. Die q-koordinate hat, wie w, typischerweise den Werte 1 und kann zum Definieren homogener Koordinaten benutzt werden (Genaueres im Abschnitt??). Die Funktion gl.gltexcoord*() zum Spezifizieren von Texturkoordinaten ist ähnlich zu gl.glvertex*(), gl.glcolor*() und gl.glnormal*(). Sie hat analoge Varianten und wird ebenfalls zwischen gl.glbegin() und gl.glend() benutzt. Üblicherweise liegen die Werte von Texturkoordinaten zwischen 0 und 1. Werte außerhalb diese Bereichs führen zu Effekten, die in Abschnitt?? beschrieben werden. Die Funktionalitäten sind void gl.gltexcoord{1234{sifd(type coords); void gl.gltexcoord{1234{sifdv(btype coords) Für letztere gibt es auch wieder Feld/Offset-Varianten. Nach einem Aufruf dieser Funktionen werden allen durch gl.glvertex*() erzeugten Punkten die aktuellen Texturkoordinaten zugeordnet, bis wieder eine gl.gltexcoord-funktion aufgerufen wird. Texturkoordinaten werden vor ihrer Verwendung immer mit der aktuellen 4 4- Texturmatrix multipliziert (für Genaueres siehe Abschnitt??) Wiederholen und Strecken von Texturen Man kann auch Texturkoordinaten außerhalb dem Intervall [0, 1] verwenden; dann wird die Textur entweder wiederholt oder in die entsprechende Richtung gestreckt. Beim Wiederholen wird einfach der Ganzzahlteil der Texturkoordinaten gestrichen, um die Texelwerte für jeden Punkt abzulesen. Hat man z.b. ein Rechteck und verwendet Texturkoordinaten von 0 bis 10 in jeder Richtung, werden 100 Exemplare der Textur kachelartig auf das Rechteck aufgebracht. Meist ist für einen nahtlosen Verlauf erwünscht, daß die Texel am oberen und unteren und am linken und rechten Rand übereinstimmen. 43

44 Beim Strecken werden für Koordinaten größer als 1 bzw. kleiner als 0 die Texturwerte für 1 bzw. 0 abgelesen und damit die Textur an den Rändern konstant auf die gewünschte Breite gedehnt. Verwendet man z.b. Texturkoordinaten von 0 bis 10 in jeder Richtung, wird ein Texturexemplar links unten im Rechteck plaziert und nach rechts und oben konstant gedehnt. Wählt man GL.GL_LINEAR als Filtermethode, entsteht eine gleich gewichtete Kombination aus Randfarbe und Texturfarbe wie folgt. Beim Wiederholen bezieht das 2 2-Feld die jeweils andere Kante der Textur ein. Also wird zwischen den Texeln an der rechten und linken Kante gemittelt, ebenso zwischen denen an der oberen und unteren Kante. Ist explizit ein Texturrand definiert, werden dessen Texel beim Mitteln benutzt. Ansonsten wird GL.GL_TEXTURE_BORDER_COLOR verwendet. (Wählt man GL.GL_NEAREST als Filtermethode, wird die Randfarbe völlig ignoriert.) Beim Strecken kann man vermeiden, daß der Rest der Fläche von der Textur betroffen wird. Dazu verwendet man Alpha-Werte von 0 für die Kanten (oder Ränder, wenn sie spezifiziert sind) der Textur. Die Deck-Texturfunktion verwendet direkt die Alpha-Werte der Textur. Bei Verwendung der anderen Texturfunktionen kann es nötig werden, mit guten Quell- und Zielfaktoren zu mischen (Genaueres siehe später). Die Effekte werden ausgelöst mit void gl.gltexparameter{if (int target, int pname, TYPE param) void gl.gltexparameter{ifv (int target, int pname, BTYPE param) Für letztere gibt es auch wieder Feld/Offset-Varianten. Der Parameter target ist entweder GL.GL_TEXTURE_2D oder GL.GL_TEXTURE_1D. Die möglichen Werte für pname und param gibt die nachfolgende Tabelle an. Parameter GL.GL_TEXTURE_WRAP_S GL.GL_TEXTURE_WRAP_T GL.GL_TEXTURE_MAG_FILTER GL.GL_TEXTURE_MIN_FILTER Werte GL.GL_CLAMP, GL.GL_REPEAT GL.GL_CLAMP, GL.GL_REPEAT GL.GL_NEAREST, GL.GL_LINEAR GL.GL_NEAREST, GL.GL_LINEAR, GL.GL_NEAREST_MIPMAP_NEAREST, GL.GL_NEAREST_MIPMAP_LINEAR, GL.GL_LINEAR_MIPMAP_NEAREST, GL.GL_LINEAR_MIPMAP_LINEAR GL.GL_TEXTURE_BORDER_COLOR beliebige vier Werte in [0, 1] GL.GL_TEXTURE_PRIORITY [0, 1] für das aktuelle Texturobjekt 44

45 Bei GL.GL_REPEAT wird die Textur s- und t-richtung wiederholt, wenn man folgende Aufrufe verwendet: gl.gltexparameteri (GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); gl.gltexparameteri (GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); Bei GL.GL_CLAMP für jede Richtung entsteht ein Exemplar der Textur, das in Streifen ausläuft, während die rechte obere Ecke zu einem großen Viereck wächst. Man kann auch in einer Richtung strecken und in der anderen wiederholen Automatische Erzeugung von Texturkoordinaten Mit Texturen kann man Höhenlinien erzeugen oder die Spiegelungen einer beliebigen Umgebung an einer glänzenden Kugel modellieren. Um diese Effekte zu erzielen, kann man JOGL die Texturkoordinaten automatisch erzeugen lassen, statt sie explizit mit gl.gltexcoord*() zu definieren. Dazu dienen die Funktionen void gl.gltexgen{ifd(int coord, int pname, TYPE param) void gl.gltexgen{ifdv(int coord, int pname, BTYPE param) Für letztere gibt es auch wieder Feld/Offset-Varianten. Der Parameter coord muss GL.GL_S, GL.GL_T, GL.GL_R oder GL.GL_Q sein und gibt an, ob die Texturkoordinate s, t, r oder q erzeugt werden soll. Der Parameter pname ist GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_PLANE oder Gl.GL_EYE_PLANE. Ist er GL.GL_TEXTURE_GEN_MODE, muss param eine Ganzzahl sein (oder, in der Feldversion der Funktion, auf eine Ganzzahl zeigen), die entweder GL.GL_OBJECT_LINEAR, GL.GL_EYE_LINEAR oder GL.GL_SPHERE_MAP ist. Diese Konstanten bestimmen, auf welche Art die Texturkoordinate bestimmt wird. Bei einem der anderen möglichen Werte für pname ist param (für die Feldversion) ein Zeiger auf ein Feld von Werten, die Parameter für die Texturerzeugung spezifizieren. Die unterschiedlichen Methoden zur Texturkoordinatenerzeugung haben unterschiedliche Verwendung. Soll eine Textur an einem bewegten Objekt dauerhaft befestigt sein, spezifiziert man die Bezugsebene am besten in Objektkoordinaten. Also würde man GL.GL_OBJECT_LINEAR benutzen, um eine Holzkugel auf eine Tischplatte zu legen. Um dynamische Höhenlinien auf bewegten Objekten zu erzeugen, spezifiziert man die Bezugsebene am besten in Kamerakoordinaten mit GL.GL_EYE_LINEAR. Diese Option ist z.b. bei der Visualisierung von Tiefenbohrungen nützlich. Wenn der Bohrer tiefer eindringt, kann seine Farbe geändert werden, um die verschiedenen Gesteinsschichten darzustellen. 45

46 GL.GL_SPHERE_MAP wird hauptsächlich für Environment-Mapping benutzt (siehe Abschnitt??) Erzeugung von Höhenlinien Zu diesem Abschnitt gehört das Beispiel Höhenlinien.java. Sind GL.GL_TEXTURE_GEN_MODE und GL.GL_OBJECT_LINEAR spezifiziert, ist die Erzeugungsfunktion eine Linearkombination der Objektkoordinaten des Punkts (x o, y o, z o, w o ): erzeugte Koordinate = p 1 x o + p 2 y o + p 3 z o + p 4 w o. Die Werte p 1,..., p 4 werden im param-argument an gl.gltexgen*v() übergeben, wobei pname auf GL.GL_OBJECT_PLANE gesetzt ist. Werden p 1,...,p 4 korrekt normalisiert, ergibt diese Funktion den Abstand des Punkts von einer Ebene. Sind z.b. p 2 = p 3 = p 4 = 0 und p 1 = 1, liefert die Funktion den Abstand zwischen dem Punkt und der Ebene x = 0. Der Abstand ist positiv auf der einen Seite der Ebene, negativ auf der anderen und 0, wenn der Punkt auf der Ebene liegt. Im folgenden Beispiel werden Höhenlinien in gleichen Abständen auf eine Teekanne gezeichnet; sie geben den jeweiligen Abstand von der Ebene x = 0 an. Die Koeffizienten für die Ebene x = 0 sind in diesem Feld: static float xequalzero [] = {1.0, 0.0, 0.0, 0.0; Da nur eine Eigenschaft dargestellt wird (der Abstand von der Ebene), genügt eine 1D-Textur. Sie ist eigentlich konstant grün, weist aber an äquidistanten Stellen eine rote Unterbrechung auf. Da die Teekanne auf der xy-ebene steht, verlaufen die Höhenlinien senkrecht zur Grundfläche. Drückt man die Taste s, ändern sich die Parameter der Bezugsebene zu static float slanted[] = {1.0, 1.0, 1.0, 0.0; und die Höhenlinien sind parallel zur Ebene x + y + z = 0, die die Teekanne schräg durchschneidet. Die ursprüngliche Ebene stellt man durch Drücken von x wieder her. Analog können durch Drücken von y und z noch andere Ebenen gewählt werden. GL.GL_REPEAT sorgt für Wiederholung der Höhenlinien. Mit gl.glenable(gl.gl_texture_gen_s) wird die Texturkoordinatenerzeugung für die s-koordinate eingeschaltet usw.; mit gl.gldisable() wird sie wieder ausgeschaltet. Bei GL.GL_OBJECT_LINEAR werden die Texturkoordinaten in Weltkoordinaten berechnet. Im Beispiel wird dies anfangs benutzt; daher bleiben die Höhenlinien senkrecht zur Grundfläche der Teekanne, unabhängig von Drehungen oder vom 46

47 Augpunkt. Drückt man aber die Taste e, ändert sich die Art der Koordinatenerzeugung zu GL.GL_EYE_LINEAR, und die Höhenlinien werden im Kamerakoordinatensystem berechnet. (Die Taste o stellt GL.GL_OBJECT_LINEAR wieder her.) Ist die Bezugsebene x = 0, ergibt sich eine Teekanne mit roten Streifen parallel zur yz-ebene, vom Augpunkt aus gesehen. Mathematisch wird der Vektor (p 1 p 2 p 3 p 4 ) mit der Inversen der Modellmatrix multipliziert, um die Werte für die Abstandsberechnung von der Ebene zu erhalten. Die Texturkoordinate wird mit der folgenden Funktion erzeugt: erzeugt Koordinate = p 1 x e + p 2 y e + p 3 z e + p 4 w e wobei (p 1 p 2 p 3 p 4 ) = (p 1 p 2 p 3 p 4 )M 1 und (x e, y e, z e, w e ) die Augkoordinaten des Punkts sind, der als p 1,...,p 4 an gl.gltexgen*() über das param- Argument mit pname = GL.GL_EYE_PLANE übergeben wird. In diesem Beispiel wurde eine einzige Texturkoordinate benutzt, um die Höhenlinien zu erzeugen. Die s- und t-koordinaten können aber auch unabhängig erzeugt werden; sie geben dann die Abstände von zwei unterschiedlichen Ebenen an. Mit einer geeigneten 2D-Textur können die resultierenden zwei Mengen von Höhenlinien gleichzeitig dargestellt werden. Man kann sogar eine Koordinate mit GL.GL_OBJECT_LINEAR und die andere mit Gl.GL_EYE_LINEAR berechnen Texturierung von Quadriken Wie im Beispiel Quadrik_Textur.java gezeigt wird, bietet JOGL die Möglichkeit, problemlos Texturen auf Quadriken aufzutragen. Hierzu erzeugt man einfach ein GLUquadrik-Objekt und bindet mit dem Befehl GLU.gluQuadricTexture(GLUquadric, boolean) die vorher mit Texture.bind() verwendete Textur an das GLUquadric-Objekt. Später kann man aus der GLUquadric dann einen Zylinder, einen Kegel oder wie im Beispiel eine Kugel entstehen lassen. Die Berechnung der Texturkoordinaten wird von JOGL automatisch übernommen Environment Mapping Zu diesem Abschnitt liefert SpiegelTorus.zip ein Beispiel. Für diese Technik muss man eine geeignete Textur definieren und dann die Texturkoordinaten von JOGL erzeugen lassen. Die verwendete Approximation beruht auf der Annahme, daß die Objekte in der Umgebung weit von den Flächen des spiegelnden Objekts sind, d.h. daß ein kleines Objekt in einem großen Raum betrachtet wird. Um eine korrekte Umgebungstextur zu erstellen, müßte man in dieser Umgebung eine große versilberte Kugel aufstellen und sie aus unendlichem Abstand mit einer Linse unendlicher Brennweite fotografieren. Um das zu approximieren, 47

48 kann man ein Foto der Umgebung mit einer Weitwinkel- oder Fischaugenkamera verwenden. Hat man so eine Textur erzeugt, ruft man den Environment-Mapping-Algorithmus von JOGL auf. Er bestimmt zu jedem Punkt des dargestellten Objekts den Punkt auf der Kugeloberfläche mit der selben Tangentenebene und färbt ihn mit der dort sichtbaren Farbe ein. Um die Texturkoordinaten für das Environment Mapping automatisch zu erzeugen, verwendet man folgende Aufrufe: gl.gltexgeni(gl.gl_s, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); gl.gltexgeni(gl.gl_t, GL.GL_TEXTURE_GEN_MODE, GL.GL_SPHERE_MAP); gl.glenable(gl.gl_texture_gen_s); gl.glenable(gl.gl_texture_gen_t); Die Konstante GL.GL_SPHERE_MAP erzeugt die richtigen Texturkoordinaten für das Environment Mapping. Wie angegeben, muss man sie jeweils für s- und t- Richtung spezifizieren. Man braucht aber keine weiteren Parameter anzugeben Weiteres Zubehör Funktionen für residente Texturen Um zu prüfen, ob eine Textur momentan resident ist, bindet man zunächst ihr Objekt und liest dann mit gl.glgettexparameter*v() die mit dem Zustand GL.GL_TEXTURE_RESIDENT assoziierten Werte ab. Will man die Residenz von n Texturen im Feld texnames prüfen, verwendet man boolean gl.glaretexturesresident (int n, IntBuffer texnames, ByteBuffer residences) Für letztere gibt es auch wieder Feld/Offset-Varianten. Das Ergebnis wird für jede genannte Textur im Feld residences abgeliefert. Außerdem wird insgesamt noch GL.GL_TRUE, wenn alle genannten Texturen resident sind und GL.GL_FALSE sonst. Die Funktion void gl.glprioritizetextures (int n, IntBuffer texnames, FloatBuffer priorities) weist den n im Feld texnames genannten Texturobjekten die Prioritäten im Feld priorities zu. Deren Werte werden auf das Intervall [0, 1] abgeschnitten. Null ist die niedrigste Priorität, Eins die höchste. Texturen mit Priorität Null sind 48

49 mit geringster Wahrscheinlichkeit resident. Natürlich gibt es auch wieder eine Feld/Offset-Variante. Für weitere Einzelheiten sei auf die Literatur verwiesen Texturproxies Bei Verwendung von Texturen muss man stets auf deren Größe achten, um Speicherplatzprobleme zu vermeiden. Daher gibt es einen speziellen Texturstellvertreter (Proxy) target, mit dem man prüfen kann, ob genügend Ressourcen vorhanden sind. Die Funktion gl.glgetintegerv (GL.GL_MAX_TEXTURE_SIZE,...) liefert die größte Dimension (Breite oder Höhe, ohne Rand) einer Textur, typischerweise die Größe der größten quadratischen Textur, die unterstützt wird. Allerdings berücksichtigt GL.GL_MAX_TEXTURE_SIZE nicht den Effekt des internen Formats einer Textur. Eine Textur, die Texel im GL.GL_RGBA16-Format speichert, kann 64 Bit pro Texel brauchen, so daß sie 16mal kleiner sein muss als eine Textur im GL.GL_LUMINANCE4-Format. (Auch Bilder mit Rand und Mipmaps können den verfügbaren Speicher weiter reduzieren.) Zur Benutzung des Proxies verwendet man den Aufruf gl.glteximage2d(gl.gl_proxy_texture_2d, internalformat, level, width, height, border, Format, type, null) Für 1D-Texturen verwendet man die entsprechenden 1D-Funktionen und Konstanten. Ist der Proxy erstellt, fragt man mit gl.glgettexlevelparameter*() die Texturzustandsvariablen ab. Sind nicht genügend Ressourcen vorhanden, werden die Texturzustandsvariablen für Breite, Höhe, Randbreite und Komponentenauflösungen auf 0 gesetzt. Die Funktion void gl.glgettexlevelparameter{ifv(int target, int level, int pname, BTYPE params) liefert in params Texturparameterwerte für eine spezifisches Detailniveau, spezifiziert als level. target definiert die Zieltextur und hat als mögliche Werte GL.GL_TEXTURE_1D, GL.GL_TEXTURE_2D, GL.GL_PROXY_TEXTURE_1D, GL.GL_PROXY_TEXTURE_2D. 49

50 Zulässige Werte für pname sind GL.GL_TEXTURE_WIDTH, GL.GL_TEXTURE_HEIGHT, GL.GL_TEXTURE_BORDER, GL.GL_TEXTURE_INTERNAL_FORMAT, GL.GL_TEXTURE_RED_SIZE, GL.GL_TEXTURE_GREEN_SIZE, GL.GL_TEXTURE_BLUE_SIZE, GL.GL_TEXTURE_ALPHA_SIZE, GL.GL_TEXTURE_LUMINANCE_SIZE, GL.GL_TEXTURE_INTENSITY_SIZE. Auch GL.GL_TEXTURE_COMPONENTS ist für pname zulässig, aber nur zur Abwärtskompatibilität mit JOGL 1.0 für JOGL 1.1 ist der empfohlene Wert GL.GL_TEXTURE_INTERNAL_FORMAT. Das folgende Programmstück zeigt die Verwendung eines Proxies um zu prüfen, ob genügend Platz für eine Textur mit RGBA-Texeln von 8 Bit Auflösung vorhanden ist. Im Erfolgsfall speichert gl.glgettexlevelparameteriv() das Internformat (hier GL.GL_RGBA8) in der Variablen Format: int Format; gl.glteximage2d(gl.gl_proxy_texture_2d, 0, Gl.GL_RGBA8, 64, 64, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, NULL); gl.glgettexlevelparameteriv(gl.gl_proxy_texture_2d, 0, GL.GL_TEXTURE_INTERNAL_FORMAT, &Format); Achtung: Proxies unterliegen einer wichtigen Beschränkung. Der Proxy sagt zwar aus, ob genügend Platz für die jeweilige Textur da ist, aber nur wenn alle Texturressourcen verfügbar sind (mit anderen Worten, wenn nur diese Textur da ist). Verbrauchen auch andere Texturen Ressourcen, so kann die Proxyabfrage zwar eine positive Antwort liefern, aber trotzdem nicht genügend Platz da sein, um die Textur resident zu halten Der Texturmatrix-Keller Texturkoordinaten werden vor dem eigentlichen Texturieren immer mit einer 4 4-Matrix multipliziert. Per Voreinstellung ist das die Identitätsmatrix, so daß explizite oder automatisch erzeugte Texturkoordinaten zunächst unverändert bleiben. Durch Änderung der Texturmatrix während des Auffrischens kann man aber die Textur auf der betreffenden Fläche verschieben, drehen, strecken oder stauchen oder Kombinationen davon anwenden. Da die Texturmatrix eine beliebige 4 4-Matrix sein darf, kann man sogar Effekte wie perspektivische Verzerrung erreichen. Nach Transformation werden die Texturkoordinaten als homogene Koordinaten interpretiert. Wie bei den anderen Matrixarten ist die Texturmatrix das oberste Element eines Kellers mit Platz für mindestens zwei Einträge. Alle Standardfunktionen zur Matrixmanipulation, wie gl.glpushmatrix(), gl.glpopmatrix(), 50

51 gl.glloadmatrix(), gl.glmultmatrix() sowie gl.glrotate*() usw. können auch auf die Texturmatrix angewendet werden. Um die aktuelle Texturmatrix zu modifizieren, muss der Matrixmodus mit gl.glmatrixmode(gl.gl_texture); umgeschaltet werden Die q-koordinate Die q-koordinate benützt man in Fällen, wo mehr als eine Projektion benötigt wird. Als Beispiel diene die Modellierung eines Spotlichts mit ungleichmäßiger Lichtverteilung, etwa heller in der Mitte oder oval aufgrund von Flügelklappen oder Linsen, die die Form des Lichtbündels verändern. Man kann die Einwirkung eines solchen Lichts auf eine ebene Fläche mit einer Textur simulieren, die der Form und Intensität des Lichts entspricht, und die dann perspektivisch auf die Fläche projiziert wird. Eine zweite perspektivische Projektion ist nötig, weil der Betrachter die Szene von einem unterschiedlichen Standpunkt aus sieht. Ein weiteres Beispiel ist eine Textur, die selbst perspektivisch verzerrt fotografiert wurde. 11 Transparenz und Farbmischung 11.1 Grundbegriffe Wir haben bereits gelegentlich die Alpha-Werte von Farben erwähnt, ohne sie genau zu erklären. Das soll nun nachgeholt werden. Der Alpha-Wert (auch Transparenz genannt) hat folgende Verwendungen. Wenn die Möglichkeit zur Farbmischung (blending) eingestellt ist, wird er benützt, um die Farbe des gerade bearbeiteten Objektfragments mit der für das aktuelle Pixel bereits im Bildpuffer eingetragenen Farbe zu mischen. Er wird zur Spezifikation von Farben und Materialeigenschaften herangezogen. Beim Alphatest werden Flächen nach ihrem Alpha-Wert behalten oder aus der Szenerie gestrichen. Ohne Mischung überschreibt jedes neu bearbeitete Fragment alle bisherig Farbinformation im Bildpuffer, so als wäre das Fragment völlig undurchsichtig. Im Mischungsmodus ist genau kontrollierbar was und wieviel von den vorhandenen Farben mit den Werten für das neue Fragment kombiniert werden soll. Damit kann man also auch (teilweise) durchscheinende Fragmente erzeugen. 51

52 Tatsächlich misst der Alpha-Wert nicht die Transparenz, sondern ihr Gegenteil, die Opazität. Transparente oder durchscheinende Flächen haben daher niedrige Alpha-Werte. Natürlich können auch mehrere Schichten verschieden transparenter Flächen entstehen, etwa wenn man durch ein Glasfenster auf die Flüssigkeit in einem Trinkglas und eine dahinter stehende Kerze blickt Quell- und Zielfaktoren Eine RGBA-Farbe ist ein Quadrupel (r, g, b, a), wobei (r, g, b)-farbe und a [0, 1] ein Alpha-Wert ist. Beim Mischen wird die Farbe des neu bearbeiteten Fragments, der Quelle (source), mit der Farbe des aktuellen Pixels, des Ziels (destination), kombiniert. Dazu werden die Quell- und Zielfarbe zunächst noch komponentenweise mit eigenen Faktoren gewichtet, die wieder als RGBA-Farben angegeben werden. Seien (r Q, g Q, b Q, a Q ) und (r Z, g Z, b Z, a Z ) der Quell- und Zielfaktor und (r q, g q, b q, a q ) und (r z, g z, b z, a z ) die Quell-und Zielfarbe. Dann ist die Mischfarbe (r Q r q + r Z r z, g Q g q + g Z g z, b Q b q + b Z b z, a Q a q + a Z a z ). Die Komponentenwerte werden dann noch auf das Intervall [0, 1]. abgeschnitten. Zunächst muss das Mischen ermöglicht werden mit gl.glenable(gl.gl_blend); mit gl.gldisable(gl.gl_blend) wird zurückgesetzt. Die Funktion void gl.glblendfunc(int sfactor, int dfactor); bestimmt mit den Parametern sfactor und dfactor, wie Quell- und Zielfarbe kombiniert werden. Deren möglichen Werte werden nachfolgend erläutert. 52

53 Konstante betroffener Faktor errechneter Faktorwert GL.GL_ZERO Quelle oder Ziel (0, 0, 0, 0) GL.GL_ONE Quelle oder Ziel (1, 1, 1, 1) GL.GL_DST_COLOR Quelle (r z, g z, b z, a z ) GL.GL_SRC_COLOR Ziel (r q, g q, b q, a q ) GL.GL_ONE_MINUS_ Quelle (1, 1, 1, 1) (r z, g z, b z, a z ) DST_COLOR GL.GL_ONE_MINUS_ Ziel (1, 1, 1, 1) (r q, g q, b q, a q ) SRC_COLOR GL.GL_SRC_ALPHA Quelle oder Ziel (a q, a q, a q, a q ) GL.GL_ONE_MINUS_ Quelle oder Ziel (1, 1, 1, 1) (a q, a q, a q, a q ) SRC_ALPHA GL.GL_DST_ALPHA Quelle oder Ziel (a z, a z, a z, a z ) GL.GL_ONE_MINUS_ Quelle oder Ziel (1, 1, 1, 1) (a z, a z, a z, a z ) DST_ALPHA GL.GL_SRC_ Quelle (f, f, f, 1) mit ALPHA_SATURATE f = min(a q, 1 a z ) Verwendet man also GL.GL_ONE für die Quelle und GL.GL_ZERO für das Ziel, so entsteht der selbe Effekt wie bei gl.gldisable(gl.gl_blend); diese Werte sind voreingestellt Einige wichtige Mischarten Nicht alle Kombinationen von Quell- und Zielfaktoren sind sinnvoll. Meist verwendet man nur einige wenige Kombinationen. Wir geben einige typische Anwendungsfälle ein. Um ein Bild hälftig aus zwei anderen zusammenzusetzen, kann man zuerst den Quellfaktor auf GL.GL_ONE und den Zielfaktor auf GL.GL_ZERO und zeichnet das erste Bild; dann setzt man den Quellfaktor auf GL.GL_SRC_ALPHA und den Zielfaktor auf GL.GL_ONE_MINUS_SRC_ALPHA und zeichnet das zweite Bild mit alpha = 0.5. Das ist mit die häufigste Mischart. Soll eine Mischung mit Anteil 0.75 des ersten und 0.25 des zweiten Bildes erzeugt werden, so zeichnet man das erste wie oben und das zweite mit alpha = Um drei Bilder gleichmäßig zu mischen, setzt man den Zielfaktor auf GL.GL_ONE und den Quellfaktor auf GL.GL_SRC_ALPHA. Dann zeichnet man jedes Bild mit alpha = Damit erhält allerdings jedes Bild nur noch ein Drittel seiner ursprünglichen Leuchtkraft, was man dann ein den nicht-überlappenden Stellen bemerkt. In Malprogrammen benötigt man Pinseleffekte: Mit jedem Pinselstrich soll ein wenig mehr von der Pinselfarbe aufs Bild aufgetragen werden, z.b. 10% Farbe im Verhältnis zur Bildfarbe. Dazu zeichnet man das Bild des Pinsels mit alpha = 0.1 und verwendet GL.GL_SRC_ALPHA für die Quelle und Gl.GL_ONE_MINUS_SRC_ALPHA für das Ziel. Der Eindruck wird noch 53

54 realistischer, wenn der Alpha-Wert sich über die Pinselfläche ändert (mehr Farbe in Pinselmitte, weniger ein den Rändern). Analog kann man einen Radiergummi darstellen, indem man dessen Farbe auf die Hintergrundfarbe setzt. Mischt man unter Verwendung der Quell- oder Zielfarben (GL.GL_DST_COLOR oder GL.GL_ONE_MINUS_DST_COLOR für den Quellfaktor und GL.GL_SRC_COLOR oder GL.GL_ONE_MINUS_SRC_COLOR für den Zielfaktor), so kann man jede Farbkomponente individuell beeinflussen. Man kann damit einen einfachen Filtereffekt erreichen. Multipliziert man z.b. den Rotanteil mit 0.8, den Grünanteil mit 0.4 und den Blauanteil mit 0.72, so erscheint das Bild wie durch einen photographischen Filter, der 20% Rot, 60% Grün und 28% Blau entfernt. Nun soll ein Bild aus drei durchscheinenden Flächen zusammengesetzt werden, die sich teilweise verdecken und alle vor einem undurchsichtigen Hintergrund liegen. Die hinterste Fläche läßt 80% des Lichts durch, die mittlere 40% und die vorderste 90%. Dazu zeichnet man zuerst den Hintergrund mit den voreingestellten Werten für die Quell- und Zielfaktoren. Dann ändert man die Faktoren auf GL.GL_SRC_ALPHA (Quelle) und GL.GL_ONE_MINUS_SRC_ALPHA(Ziel). Dann zeichnet man die hinterste Fläche mit alpha = 0.2, die mittlere mit alpha = 0.6 und die vorderste mit alpha = 0.1. Den Effekt eines nicht-rechteckigen Rasterbilds kann man erzeugen, indem man den einzelnen Fragmenten im Bild unterschiedliche Alpha-Werte gibt. Jedes durchsichtige Fragment erhält alpha = 0 und jedes undurchsichtige alpha = 1. Z.B kann man ein Polygon in Form eines Baums zeichnen und mit einer Laubtextur belegen. Gibt man den Teilen der rechteckigen Textur, die nicht zum Baum gehören, den Alpha-Wert 0, so sind sie für den Betrachter nicht mehr zu sehen. Diese Methode heißt Billboarding; sie ist viel schneller als eine Modellierung des Baums mit Polygonen im Dreidimensionalen. Ein Beispiel zeigt das nachfolgende Bild. Abbildung 5. Billboarding 54

Kapitel 6. Vererbung

Kapitel 6. Vererbung 1 Kapitel 6 2 Ziele Das sprinzip der objektorientierten Programmierung verstehen Und in Java umsetzen können Insbesondere folgende Begriffe verstehen und anwenden können: Ober/Unterklassen Subtyping Überschreiben

Mehr

Grafikausgabe mit dem Abstract- Windowing-Toolkit. Eine Einführung

Grafikausgabe mit dem Abstract- Windowing-Toolkit. Eine Einführung Grafikausgabe mit dem Abstract- Windowing-Toolkit Eine Einführung Inhalt Einführung Grundlegende Eigenschaften des Abstract-Windowing- Toolkit (AWT) Grundlagen Grafikausgabe Linien zeichnen Rechtecke zeichnen

Mehr

Abschnitt 9: Schnittstellen: Interfaces

Abschnitt 9: Schnittstellen: Interfaces Abschnitt 9: Schnittstellen: Interfaces 9. Schnittstellen: Interfaces 9.1 Die Idee der Schnittstellen 9.2 Schnittstellen in Java 9.3 Marker-Interfaces 9.4 Interfaces und Hilfsklassen 9.5 Zusammenfassung

Mehr

Kapitel 6. Vererbung

Kapitel 6. Vererbung 1 Kapitel 6 2 Ziele Das sprinzip der objektorientierten Programmierung verstehen Und in Java umsetzen können Insbesondere folgende Begriffe verstehen und anwenden können: Ober/Unterklassen Subtyping Überschreiben

Mehr

Texture Mapping. Texturen

Texture Mapping. Texturen Grundlagen - Eine Textur ist ein Bild, das auf eine Oberfläche einer Geometrie aufgebracht ist - erlauben eine realistischere Darstellung von Oberflächen - können auf alle Primitive, nicht nur Polygone

Mehr

Kapitel 6. Vererbung

Kapitel 6. Vererbung Kapitel 6 Vererbung Vererbung 1 Ziele Das Vererbungsprinzip der objektorientierten Programmierung verstehen Und in Java umsetzen können Insbesondere folgende Begriffe verstehen und anwenden können: Ober/Unterklassen

Mehr

Klausur vom 14. Juni 2004. Informatik 4

Klausur vom 14. Juni 2004. Informatik 4 Berner Fachhochschule Hochschule für Technik und Informatik, HTI Fachbereich Elektro- und Kommunikationstechnik Labor für Technische Informatik, Burgdorf Klasse: EV02-1 Name, Vorname: Klausur vom 14. Juni

Mehr

Workshop: Einführung in die 3D-Computergrafik. Julia Tolksdorf Thies Pfeiffer Christian Fröhlich Nikita Mattar

Workshop: Einführung in die 3D-Computergrafik. Julia Tolksdorf Thies Pfeiffer Christian Fröhlich Nikita Mattar Workshop: Einführung in die 3D-Computergrafik Julia Tolksdorf Thies Pfeiffer Christian Fröhlich Nikita Mattar 1 Organisatorisches Tagesablauf: Vormittags: Theoretische Grundlagen Nachmittags: Bearbeitung

Mehr

Universität Augsburg, Institut für Informatik Sommersemester 2005 Prof. Dr. Werner Kießling 15. Oktober 2005 Dr. Alfons Huhn, Timotheus Preisinger

Universität Augsburg, Institut für Informatik Sommersemester 2005 Prof. Dr. Werner Kießling 15. Oktober 2005 Dr. Alfons Huhn, Timotheus Preisinger Universität Augsburg, Institut für Informatik Sommersemester 2005 Prof. Dr. Werner Kießling 15. Oktober 2005 Dr. Alfons Huhn, Timotheus Preisinger Informatik II Hinweise: Die Bearbeitungszeit beträgt 90

Mehr

Graphische Benutzungsoberflächen

Graphische Benutzungsoberflächen Graphische Benutzungsoberflächen Graphische Benutzungsoberflächen (graphical user interfaces, GUI) dienen zur interaktiven Bedienung von Programmen, Ein- und Ausgabe mit graphischen Techniken und visuellen

Mehr

PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl

PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl PROGRAMMIEREN MIT C Allgemeine hinweise Alles was hier beschrieben wird, soll auch ausprobiert werden. Warum C? Weil die coolen Dinge mit C am einfachsten gehen. Das werden wir in den folgenden Übungen

Mehr

Probeklausur: Programmierung WS04/05

Probeklausur: Programmierung WS04/05 Probeklausur: Programmierung WS04/05 Name: Hinweise zur Bearbeitung Nimm Dir für diese Klausur ausreichend Zeit, und sorge dafür, dass Du nicht gestört wirst. Die Klausur ist für 90 Minuten angesetzt,

Mehr

von Anja Austermann Drag and Drop

von Anja Austermann Drag and Drop von Anja Austermann Drag and Drop »Drag and Drop«ist die Bezeichnung für den Datentransfer zwischen unterschiedlichen Anwendungen mit grafischer Benutzeroberfläche. Zur Zeit arbeitet Drag and Drop in Java

Mehr

Eine Einführung in OpenGL

Eine Einführung in OpenGL Eine Einführung in OpenGL Inhaltsverzeichnis 1 Übersicht 2 1.1 Was ist OpenGL?........................... 2 1.2 Was leistet OpenGL?......................... 2 2 Erste Schritte mit OpenGL 3 2.1 Grundstrukturen...........................

Mehr

5.5.8 Öffentliche und private Eigenschaften

5.5.8 Öffentliche und private Eigenschaften 5.5.8 Öffentliche und private Eigenschaften Schnittstellen vs. Implementierungen: Schnittstelle einer Klasse beschreibt, was eine Klasse leistet und wie sie benutzt werden kann, ohne dass ihre Implementierung

Mehr

4 Codierung nach Viginere (Lösung)

4 Codierung nach Viginere (Lösung) Kapitel 4 Codierung nach Viginere (Lösung) Seite 1/14 4 Codierung nach Viginere (Lösung) 4.1 Einführung Blaise de Vigenère lebte von 1523 bis 1596 in Frankreich und war nach dem Studium bei verschiedenen

Mehr

Institut fu r Informatik

Institut fu r Informatik Technische Universita t Mu nchen Institut fu r Informatik Lehrstuhl fu r Bioinformatik Einfu hrung in die Programmierung fu r Bioinformatiker Prof. B. Rost, L. Richter Java, Objektorientierung 5.1 (U )

Mehr

Schritt 1 - Ein Spielfeld

Schritt 1 - Ein Spielfeld Schritt 1 - Ein Spielfeld Wir beginnen mit zwei einfachen Java-Klassen, dem eigentlichen Spielfeld und dem Applet zum Anzeigen des Spielfeldes (und später der Buttons und der anderen Bedienelemente). Hier

Mehr

3. Konzepte der objektorientierten Programmierung

3. Konzepte der objektorientierten Programmierung 3. Konzepte der objektorientierten Programmierung 3.1 Basiskonzepte 3.2 Generalisierung / Spezialisierung 3.3 Aggregation 3.4 Assoziation 3.5 Nachrichten 3.6 Polymorphismus 3. Konzepte der Objektorientierung

Mehr

1 Polymorphie (Vielgestaltigkeit)

1 Polymorphie (Vielgestaltigkeit) 1 Polymorphie (Vielgestaltigkeit) Problem: Unsere Datenstrukturen List, Stack und Queue können einzig und allein int-werte aufnehmen. Wollen wir String-Objekte, andere Arten von Zahlen oder andere Objekttypen

Mehr

OpenGL for Java OpenGL for Java Prof. Dr. V. Stahl

OpenGL for Java OpenGL for Java Prof. Dr. V. Stahl OpenGL for Java Ziele Bewegte Simulationen grafisch darstellen können (effizient, realistisch, dreidimensional) Grundfunktionen von OpenGL beherrschen Mathematische Voraussetzungen für Computer Grafik

Mehr

Bilder. 2D Spiele programmieren in Java. Alpha channel. Formate. Optimierung. Empfehlung

Bilder. 2D Spiele programmieren in Java. Alpha channel. Formate. Optimierung. Empfehlung 2D Spiele programmieren in Java Teil 3: Bilder, Animationen Dr. Katja Wegner Dr. Ursula Rost Bilder Sind vielfach in Spielen einsetzbar (Menüs, Hintergrund, Objekte) Eigenschaften: Typ (e.g. bitmap, vector)

Mehr

Computer Graphik. Mitschrift von www.kuertz.name

Computer Graphik. Mitschrift von www.kuertz.name Computer Graphik Mitschrift von www.kuertz.name Hinweis: Dies ist kein offizielles Script, sondern nur eine private Mitschrift. Die Mitschriften sind teweilse unvollständig, falsch oder inaktuell, da sie

Mehr

Ab jetzt: Java ohne Kara

Ab jetzt: Java ohne Kara Java ohne Kara Ab jetzt: Java ohne Kara Ziel: Erfahrungen sammeln mit ersten Java Programmen JavaKara -> Java Ablauf in JavaKara: 1. Programm schreiben 2. Kompilieren 3. Programm starten Ablauf in Java

Mehr

Kapitel 0. Einführung. 0.1 Was ist Computergrafik? 0.2 Anwendungsgebiete

Kapitel 0. Einführung. 0.1 Was ist Computergrafik? 0.2 Anwendungsgebiete Kapitel 0 Einführung 0.1 Was ist Computergrafik? Software, die einen Computer dazu bringt, eine grafische Ausgabe (oder kurz gesagt: Bilder) zu produzieren. Bilder können sein: Fotos, Schaltpläne, Veranschaulichung

Mehr

Programmieren mit DirectX

Programmieren mit DirectX 2D 3D Programmieren mit DirectX Teil 3: Malte Ried Fachhochschule Gießen-Friedberg 30. Oktober 2005 Inhalt 2D 3D 1 2D 2 3D 3 2D 3D Bis jetzt Windows-Fenster, das man schließen kann initialisiertes Direct3D

Mehr

Übersicht. Informatik 2 Teil 3 Anwendungsbeispiel für objektorientierte Programmierung

Übersicht. Informatik 2 Teil 3 Anwendungsbeispiel für objektorientierte Programmierung Übersicht 3.1 Modell Konto 3.2 Modell Konto - Erläuterungen 3.3 Benutzer Ein- und Ausgabe mit Dialogfenster I 3.4 Benutzer Ein- und Ausgabe mit Dialogfenster II 3.5 Klassen- und Objekteigenschaften des

Mehr

:= Modellabbildung. Bildsynthese (Rendering) Bildsynthese

:= Modellabbildung. Bildsynthese (Rendering) Bildsynthese Geometrisches Modell bestehend aus Datenstrukturen zur Verknüpfung geometrischer Primitive, welche eine Gesamtszene beschreiben Bildsynthese := Modellabbildung Pixelbasiertes Modell zur Darstellung eines

Mehr

Java: Vererbung. Teil 3: super() www.informatikzentrale.de

Java: Vererbung. Teil 3: super() www.informatikzentrale.de Java: Vererbung Teil 3: super() Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und IMMER zuerst den Konstruktor der Elternklasse auf! Konstruktor und Vererbung Kindklasse ruft SELBSTSTÄNDIG und

Mehr

Kurzanleitung Zeichnungsmodul ACD Chemsketch 11.0 Freeware

Kurzanleitung Zeichnungsmodul ACD Chemsketch 11.0 Freeware U. Schütz Seite 1 von 7 Kurzanleitung Zeichnungsmodul ACD Chemsketch 11.0 Freeware Draw Durch Anklicken der Schaltfläche Draw wechselt das Programm in den Zeichnungsmodus. Optionen Show Grid Raster anzeigen

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Konstruktor, Statische Methoden Packages Prof. Dr. Stefan Fischer Institut für Telematik, Universität zu Lübeck http://www.itm.uni-luebeck.de/people/fischer Initialisierung von Datenstrukturen

Mehr

3 Objektorientierte Konzepte in Java

3 Objektorientierte Konzepte in Java 3 Objektorientierte Konzepte in Java 3.1 Klassendeklarationen Fragen an die Klassendeklaration: Wie heißt die Klasse? Wer darf auf die Klasse und ihre Attribute/Methoden zugreifen? Ist die Klasse eine

Mehr

Dr. Monika Meiler. Inhalt

Dr. Monika Meiler. Inhalt Inhalt 5 Referenzdatentypen - Felder... 5-2 5.1 Eindimensionale Felder - Vektoren... 5-3 5.1.1 Vereinbarung... 5-3 5.1.2 Referenzen sind keine Felder... 5-4 5.1.3 Kopieren eindimensionaler Felder... 5-6

Mehr

Prüfungszeuch im Fach Objektorientierte Programmierung WS 2000

Prüfungszeuch im Fach Objektorientierte Programmierung WS 2000 Prüfungszeuch im Fach Objektorientierte Programmierung WS 2000 A. Beschreibung der Projektarbeit. Welche Aufgabe haben Sie im Rahmen der Projektarbeit gelöst? 2. Mit welchen Tools bzw. Programmen (Anwendung,

Mehr

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI Universität Osnabrück Drei-Schichten-Architektur 3 - Objektorientierte Programmierung in Java Vorlesung 6: 3-Schichten-Architektur Fachkonzept - GUI SS 2005 Prof. Dr. F.M. Thiesing, FH Dortmund Ein großer

Mehr

Vorkurs C++ Programmierung

Vorkurs C++ Programmierung Vorkurs C++ Programmierung Klassen Letzte Stunde Speicherverwaltung automatische Speicherverwaltung auf dem Stack dynamische Speicherverwaltung auf dem Heap new/new[] und delete/delete[] Speicherklassen:

Mehr

"rendern" = ein abstraktes geometrisches Modell sichtbar machen

rendern = ein abstraktes geometrisches Modell sichtbar machen 3. Grundlagen des Rendering "rendern" = ein abstraktes geometrisches Modell sichtbar machen Mehrere Schritte: Sichtbarkeitsberechnung Beleuchtungsrechnung Projektion Clipping (Abschneiden am Bildrand)

Mehr

Applets Belebung von Webseiten. Dipl.-Ing. Wolfgang Beer

Applets Belebung von Webseiten. Dipl.-Ing. Wolfgang Beer Applets Belebung von Webseiten Dipl.-Ing. Wolfgang Beer Was sind Applets? Java Klassen, die spezielle Richtlinien befolgen, um: "in Internet-Browsern lauffähig zu sein" Somit ist, komplexere Funktionalität,

Mehr

Objektorientierte Programmierung. Kapitel 12: Interfaces

Objektorientierte Programmierung. Kapitel 12: Interfaces 12. Interfaces 1/14 Objektorientierte Programmierung Kapitel 12: Interfaces Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2012/13 http://www.informatik.uni-halle.de/ brass/oop12/

Mehr

13 OOP MIT DELPHI. Records und Klassen Ein Vergleich

13 OOP MIT DELPHI. Records und Klassen Ein Vergleich 13 OOP MIT DELPHI Delphi war früher "Object Pascal". Dieser Name impliziert eine Funktionalität, welche in der Welt der Programmierung nicht mehr wegzudenken ist: die objektorientierte Programmierung,

Mehr

Graphische Datenverarbeitung und Bildverarbeitung

Graphische Datenverarbeitung und Bildverarbeitung Graphische Datenverarbeitung und Bildverarbeitung Hochschule Niederrhein Clippen in 2D und 3D Graphische DV und BV, Regina Pohle, 19. Clippen in 2D und 3D 1 Einordnung in die Inhalte der Vorlesung Einführung

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Objektorientierte Programmierung 1 Geschichte Dahl, Nygaard: Simula 67 (Algol 60 + Objektorientierung) Kay et al.: Smalltalk (erste rein-objektorientierte Sprache) Object Pascal, Objective C, C++ (wiederum

Mehr

Abteilung Informatik, JFC/Swing 2004 Diego Schmidlin V2.2

Abteilung Informatik, JFC/Swing 2004 Diego Schmidlin V2.2 Inhalt 1. Printing API 1. Übersicht 2. Vorgehen 3. Beispiel 2. Klasse PrintUtils 3. Mehrere Seiten drucken Folie 1 Lernziele Sie wissen, wie Sie Swing-Komponenten ausdrucken können Sie kennen den Aufbau

Mehr

Planare Projektionen und Betrachtungstransformation. Quelle: Angel (2000)

Planare Projektionen und Betrachtungstransformation. Quelle: Angel (2000) Planare Projektionen und Betrachtungstransformation Quelle: Angel (2) Gliederung Einführung Parallelprojektionen Perspektivische Projektionen Kameramodell und Betrachtungstransformationen Mathematische

Mehr

GUI Programmierung in Java

GUI Programmierung in Java vs und niemals mischen! Daher muss man sich für eine Klasse entscheiden 1 (Abstract Window Toolkit) schwergewichtige Alle Elemente werden vom Betriebssytem gemalt sehen aus wie alle anderen Programme auf

Mehr

Beispiel: Methode mit einem Fehler. Diese Methode wird problematisch, wenn von außen eine Dauer von 0 Sekunden angegeben wird, etwa im Aufruf

Beispiel: Methode mit einem Fehler. Diese Methode wird problematisch, wenn von außen eine Dauer von 0 Sekunden angegeben wird, etwa im Aufruf 16 Exceptions Zur Behandlung unerwarteter Situationen bietet Java Unterstützung in Form von Exceptions oder Ausnahmen. Den Sinn von Exceptions können wir Ihnen an einem kleinen Beispiel klarmachen. Nehmen

Mehr

Institut fu r Informatik

Institut fu r Informatik Technische Universita t Mu nchen Institut fu r Informatik Lehrstuhl fu r Bioinformatik Einfu hrung in die Programmierung fu r Bioinformatiker Prof. B. Rost, L. Richter WS 2013 Aufgabenblatt 3 18. November

Mehr

Prinzipien Objektorientierter Programmierung

Prinzipien Objektorientierter Programmierung Prinzipien Objektorientierter Programmierung Valerian Wintner Inhaltsverzeichnis 1 Vorwort 1 2 Kapselung 1 3 Polymorphie 2 3.1 Dynamische Polymorphie...................... 2 3.2 Statische Polymorphie........................

Mehr

Grundlagen Programmierung

Grundlagen Programmierung 13. Aufgabe (13 Punkte) Schreiben Sie eine neue Klasse Zahlenanalyse, mit der Integer-Objekte genauer betrachtet werden können. Bei den zu entwickelnden Methoden kann es immer sinnvoll sein, sich den Ablauf

Mehr

Javakurs für Anfänger

Javakurs für Anfänger Javakurs für Anfänger Einheit 02: Klassen & Objekte Lorenz Schauer Lehrstuhl für Mobile und Verteilte Systeme Heutige Agenda 1. Teil: Klassen Grundstruktur einer Java-Klasse Eigenschaften (Attribute) Variablen

Mehr

Bearbeitungszeit: 120 Minuten. Kommentare kosten Zeit; kommentieren Sie ihr Programm nur da, wo der Code alleine nicht verständlich wäre.

Bearbeitungszeit: 120 Minuten. Kommentare kosten Zeit; kommentieren Sie ihr Programm nur da, wo der Code alleine nicht verständlich wäre. Fakultät IV Elektrotechnik/Informatik Klausur Einführung in die Informatik I für Elektrotechniker Name:... Matr.-Nr.... Bearbeitungszeit: 120 Minuten Bewertung (bitte offenlassen : ) Aufgabe Punkte Erreichte

Mehr

Java Schulung (Java 2 Java Development Kit 5 / 6)

Java Schulung (Java 2 Java Development Kit 5 / 6) 2. Grundlagen der Objektorientierung 2.1 Klassen, Attribute, Methoden Klassen Eine Klasse beschreibt als Bauplan Gemeinsamkeiten einer Menge von Objekten ist also ein Modell, auf dessen Basis Objekte erstellt

Mehr

Swing :Komponenten I (Teil 2)

Swing :Komponenten I (Teil 2) l Bei Swing handelt es sich um eine Programmierschnittstelle und Grafikbibliothek zum Programmieren von grafischen Benutzeroberflächen l Swing stellt eine Menge von Klassen zur Verfügung l Swing wurde

Mehr

5.4 Klassen und Objekte

5.4 Klassen und Objekte 5.4 Klassen und Objekte Zusammenfassung: Projekt Figuren und Zeichner Figuren stellt Basisklassen für geometrische Figuren zur Verfügung Zeichner bietet eine übergeordnete Klasse Zeichner, welche die Dienstleistungen

Mehr

4. Kapitel 3D Engine Geometry

4. Kapitel 3D Engine Geometry 15.11.2007 Mathematics for 3D Game Programming & Computer Graphics 4. Kapitel 3D Engine Geometry Anne Adams & Katharina Schmitt Universität Trier Fachbereich IV Proseminar Numerik Wintersemester 2007/08

Mehr

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung Annabelle Klarl Zentralübung zur Vorlesung Einführung in die Informatik: http://www.pst.ifi.lmu.de/lehre/wise-13-14/infoeinf WS13/14 Action required now 1. Smartphone: installiere die App "socrative student"

Mehr

Grafikprogrammierung (Echtzeitrendering)

Grafikprogrammierung (Echtzeitrendering) (Echtzeitrendering) erfordert Unterstützung für beide Aufgaben der Computergrafik Geometrische Modellierung Datenstrukturen für geometrische Modelle Schnittstellen für deren Kombination Bildsynthese Rendering

Mehr

Tutorial Spieleentwicklung mit OpenGL und Java. oder. JOGLn in Java. Prof. Dr. W. P. Kowalk Universität Oldenburg kowalk@informatik.uni-oldenburg.

Tutorial Spieleentwicklung mit OpenGL und Java. oder. JOGLn in Java. Prof. Dr. W. P. Kowalk Universität Oldenburg kowalk@informatik.uni-oldenburg. Tutorial Spieleentwicklung mit OpenGL und Java oder JOGLn in Java Prof. Dr. W. P. Kowalk Universität Oldenburg kowalk@informatik.uni-oldenburg.de August 2005 Inhaltsverzeichnis 1 Einführung...4 1.1 Aufbau

Mehr

Diana Lange. GENERATIVE GESTALTUNG Komplexe Datentypen: PShape

Diana Lange. GENERATIVE GESTALTUNG Komplexe Datentypen: PShape Diana Lange GENERATIVE GESTALTUNG Komplexe Datentypen: PShape EINFÜHRUNG In diesem Foliensatz geht es um den Import und die Darstellung von vektorbasierten Bildmaterial in Processing. Vektorgrafiken basieren,

Mehr

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12. Kapitel 7. Grafische Benutzeroberflächen

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12. Kapitel 7. Grafische Benutzeroberflächen 1 Kapitel 7 Ziele 2 (Graphical User Interfaces) als Anwendungsbeispiel für die objektorientierte Programmierung kennenlernen Benutzung von Vererbung zur Erstellung individueller GUI-Klassen durch Erweiterung

Mehr

Deklarationen in C. Prof. Dr. Margarita Esponda

Deklarationen in C. Prof. Dr. Margarita Esponda Deklarationen in C 1 Deklarationen Deklarationen spielen eine zentrale Rolle in der C-Programmiersprache. Deklarationen Variablen Funktionen Die Deklarationen von Variablen und Funktionen haben viele Gemeinsamkeiten.

Mehr

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden.

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden. Grundwissen Informatik Objekt Attribut Methoden Als Objekte bezeichnet man alle Gegenstände, Dinge, Lebewesen, Begriffe oder Strukturen unserer Welt ( Autos, Räume, Bakterien, Lehrer, Schüler, Kunden,

Mehr

Einbindung der Tastatur

Einbindung der Tastatur Einbindung der Tastatur Auch die Tastatur kann man wie die Maus zur interaktiven Programmsteuerung verwenden. Bei der Maus ist stets klar, welche grafische Komponente bei einem Klick oder einer Bewegung

Mehr

Programmieren in Java

Programmieren in Java Programmieren in Java objektorientierte Programmierung 2 2 Zusammenhang Klasse-Datei In jeder *.java Datei kann es genau eine public-klasse geben wobei Klassen- und Dateiname übereinstimmen. Es können

Mehr

DHBW Karlsruhe, Vorlesung Programmieren, Events Musterlösung

DHBW Karlsruhe, Vorlesung Programmieren, Events Musterlösung DHBW Karlsruhe, Vorlesung Programmieren, Events Musterlösung Aufgabe Editor package BA.GUI.Swing; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.logging.level; import java.util.logging.logger;

Mehr

Folge 18 - Vererbung

Folge 18 - Vererbung Workshop Folge 18 - Vererbung 18.1 Ein einfacher Fall der Vererbung Schritt 1 - Vorbereitungen Besorgen Sie sich - vielleicht aus einer der Übungen der Folge 17 - ein fertiges und lauffähiges Listenprojekt,

Mehr

Erste Schritte mit HG 2

Erste Schritte mit HG 2 Erste Schritte mit HG 2 Malte Ried FH-Gießen Version: 1.0 21. November 2003 Inhaltsverzeichnis 1 Einführung 2 2 Allgemeines 2 2.1 Koordinaten...................................... 2 2.2 Farben.........................................

Mehr

Graphic Coding. Klausur. 9. Februar 2007. Kurs A

Graphic Coding. Klausur. 9. Februar 2007. Kurs A Graphic Coding Klausur 9. Februar 2007 Kurs A Name: Matrikelnummer: Hinweise - Es sind keine Hilfsmaterialien erlaubt. (Keine Bücher, Taschenrechner, Handys) - Sie haben zwei Stunden Zeit. - Insgesamt

Mehr

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12 Grundlagen: Folge 19 - Bäume 19.1 Binärbäume - Allgemeines Unter Bäumen versteht man in der Informatik Datenstrukturen, bei denen jedes Element mindestens zwei Nachfolger hat. Bereits in der Folge 17 haben

Mehr

3 Objektorientierte Konzepte in Java

3 Objektorientierte Konzepte in Java 3 Objektorientierte Konzepte in Java Bisherige Beobachtungen zu Objekten: werden in Klassen zusammengefasst besitzen Eigenschaften und Verhalten verbergen private Informationen werden geboren, leben und

Mehr

Tutoren Simon Andermatt Lukas Beck. Alexis Peter Thomas Ritter

Tutoren Simon Andermatt Lukas Beck. Alexis Peter Thomas Ritter UNIVERSITÄT BASEL Dozent Prof. Dr. Thomas Vetter Departement Informatik Assistenten Brian Amberg Andreas Forster Tutoren Simon Andermatt Lukas Beck Webseite http://informatik.unibas.ch/lehre/hs10/cs101/index.html

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Dr. Dietrich Boles Aufgaben zu UE16-Rekursion (Stand 09.12.2011) Aufgabe 1: Implementieren Sie in Java ein Programm, das solange einzelne Zeichen vom Terminal einliest, bis ein #-Zeichen

Mehr

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 14/15. Kapitel 11. Fehler und Ausnahmen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 14/15. Kapitel 11. Fehler und Ausnahmen 1 Kapitel 11 Fehler und Ausnahmen Fehler und Ausnahmen 1 Ziele Fehlerquellen in Programmen und bei der Programmausführung verstehen Das Java-Konzept der Ausnahmen als Objekte kennenlernen Ausnahmen auslösen

Mehr

Tutoren Jan Ebbe Pat Mächler Valentino Rugolo Sascha Scherrer. Grundlagen der Programmierung (CS101) - Blatt 8 Theorie [4 Punkte] - Praxis [12 Punkte]

Tutoren Jan Ebbe Pat Mächler Valentino Rugolo Sascha Scherrer. Grundlagen der Programmierung (CS101) - Blatt 8 Theorie [4 Punkte] - Praxis [12 Punkte] UNIVERSITÄT BASEL Dozent Prof. Dr. Thomas Vetter Departement Informatik Bernoullistrasse 16 CH 4056 Basel Assistenten Bernhard Egger Andreas Forster Tutoren Jan Ebbe Pat Mächler Valentino Rugolo Sascha

Mehr

Informatik I Eprog HS10

Informatik I Eprog HS10 Department of Informatics software evolution & architecture lab Informatik I Eprog HS10 Übung 5 1 Aufgabe: Konstruktoren und statische Variablen 1.1 Lernziele 1. Sie können ein Java Projekt in Eclipse

Mehr

Interaktive Elemente, GUI-Programmierung

Interaktive Elemente, GUI-Programmierung Softwaretechnik für IM, WS2015/2016 http://knopper.net/bw/swt/ Übung 4 Interaktive Elemente, GUI-Programmierung 1. Schreiben Sie ein Programm (wahlweise als Applet oder Applikation, oder beides), das die

Mehr

Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden.

Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden. Einfache Ein- und Ausgabe mit Java 1. Hallo-Welt! Das erste Programm soll einen Text zum Bildschirm schicken. Es kann mit jedem beliebigen Texteditor erstellt werden. /** Die Klasse hello sendet einen

Mehr

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen Algorithmen und Datenstrukturen Tafelübung 04 Referenzen, Overloading, Klassen(hierarchien) Clemens Lang T2 18. Mai 2010 14:00 16:00, 00.152 Tafelübung zu AuD 1/13 Organisatorisches Nächster Übungstermin

Mehr

Java Projekt: Tic Tac Toe + GUI

Java Projekt: Tic Tac Toe + GUI Java Projekt: Tic Tac Toe + GUI Rechnerpraktikum aus Programmierung im WS 2005/06 unter der Leitung von Dr. Michael Hahsler Tadeh Amirian (h0253821) 10.01.2006 1) Problemdefinition Beim TicTacToe Spiel

Mehr

i n g e n i e u r b ü r o f ü r s o f t w a r e t e c h n o l o g i e w w w. v o e l t e r. d e Servlet Debugging

i n g e n i e u r b ü r o f ü r s o f t w a r e t e c h n o l o g i e w w w. v o e l t e r. d e Servlet Debugging Servlet Debugging Markus Völter, voelter@acm.org, www.voelter.de Bei der Arbeit mit Servlets kommt man recht schnell an den Punkt, an dem man Servlets vernünftig testen oder debuggen will. Mit Hilfe des

Mehr

Lektion 6: Prozeduren mit Parametern Übergabe von Werten

Lektion 6: Prozeduren mit Parametern Übergabe von Werten Lektion 6: Prozeduren mit Parametern Übergabe von Werten 29 Bearbeitet von Karoline Selbach In den vorherigen Abschnitten haben wir wichtige Befehle zur Turtlegeometrie kennen gelernt. Mit Hilfe dieser

Mehr

PIWIN 1 Übung Blatt 5

PIWIN 1 Übung Blatt 5 Fakultät für Informatik Wintersemester 2008 André Gronemeier, LS 2, OH 14 Raum 307, andre.gronemeier@cs.uni-dortmund.de PIWIN 1 Übung Blatt 5 Ausgabedatum: 19.12.2008 Übungen: 12.1.2009-22.1.2009 Abgabe:

Mehr

Java Einführung Methoden in Klassen

Java Einführung Methoden in Klassen Java Einführung Methoden in Klassen Lehrziel der Einheit Methoden Signatur (=Deklaration) einer Methode Zugriff/Sichtbarkeit Rückgabewerte Parameter Aufruf von Methoden (Nachrichten) Information Hiding

Mehr

Einführung in OpenGL. Einführung in OpenGL

Einführung in OpenGL. Einführung in OpenGL OpenGL: Einführung/Standard - OpenGL (Open Graphics Library) ist ein Standard für 3D Rendering und 3D Hardware-Beschleunigung - OpenGL läuft unter Windows, MacOS, Linux, Unix, - Website: http://opengl.org

Mehr

Slices und Rollover für die Startseite einer Bildergalerie

Slices und Rollover für die Startseite einer Bildergalerie Slices und Rollover für die Startseite einer Bildergalerie Die größte Frage bei einer Webseite ist es, auf ggf. viele Informationen von der relativ kleinen Fläche eines Bildschirmes zu verweisen. Dabei

Mehr

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005 Einführung in die objektorientierte Programmierung mit Java Klausur am 19. Oktober 2005 Matrikelnummer: Nachname: Vorname: Semesteranzahl: Die Klausur besteht aus drei Frageblöcken zu den Inhalten der

Mehr

Universität Augsburg. 20. April 2012. B. Möller (U. Augsburg) Computergraphik SS12 20. April 2012 1 / 6

Universität Augsburg. 20. April 2012. B. Möller (U. Augsburg) Computergraphik SS12 20. April 2012 1 / 6 Kapitel 1 Einführung B. Möller Universität Augsburg 20. April 2012 B. Möller (U. Augsburg) Computergraphik SS12 20. April 2012 1 / 6 Begriffsdefinition Computergrafik: realistische Darstellung realer oder

Mehr

Aufgabenblatt Nr. 5 Generizität und TicTacToe

Aufgabenblatt Nr. 5 Generizität und TicTacToe Aufgabenblatt Nr. 5 Generizität und TicTacToe 1 Generische Sortier-Methode 1.1 Aufgabe: Entwickeln einer generischen Sortiermethode für Objekte mit der Schnittstelle Comparable Ihnen ist aus der Vorlesung

Mehr

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren: 5. Abstrakte Klassen Beispiel 5. Abstrakte Klassen 5. Abstrakte Klassen Beispiel Beispiel (3) Angenommen, wir wollen die folgende Klassenhierarchie implementieren: Probleme des Implementierungsvorschlags:

Mehr

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag Ludwig-Maximilians-Universität München WS 2015/16 Institut für Informatik Übungsblatt 9 Prof. Dr. R. Hennicker, A. Klarl Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung:

Mehr

Java Einführung VARIABLEN und DATENTYPEN Kapitel 2

Java Einführung VARIABLEN und DATENTYPEN Kapitel 2 Java Einführung VARIABLEN und DATENTYPEN Kapitel 2 Inhalt dieser Einheit Variablen (Sinn und Aufgabe) Bezeichner Datentypen, Deklaration und Operationen Typenumwandlung (implizit/explizit) 2 Variablen

Mehr

Objektorientierung: Klassen und Objekte

Objektorientierung: Klassen und Objekte Objektorientierung: Klassen und Objekte Klasse: Beschreibung für eine Menge von Objekten Schablone, Bauplan abstrakte Form Objekt: Instanz einer Klasse konkreter Inhalt (Werte) Klassen bestehen aus Attributen

Mehr

Programmentwicklung I für Hörer anderer Fachrichtungen -Wintersemester 2003/04- Abschlussklausur 20.02.2004

Programmentwicklung I für Hörer anderer Fachrichtungen -Wintersemester 2003/04- Abschlussklausur 20.02.2004 Programmentwicklung I für Hörer anderer Fachrichtungen -Wintersemester 2003/04- Abschlussklausur 20.02.2004 Name : Vorname : Matrikelnummer : Hauptfach : Nebenfach/Fachrichtung Hinweise : 1. Überprüfen

Mehr

Fakultät Angewandte Informatik Programmierung verteilter Systeme 28.11.2011. Übungen zur Vorlesung Informatik II, Blatt 6

Fakultät Angewandte Informatik Programmierung verteilter Systeme 28.11.2011. Übungen zur Vorlesung Informatik II, Blatt 6 WS 2011/12 Fakultät Angewandte Informatik Programmierung verteilter Systeme 28.11.2011 Prof. Dr. Bernhard Bauer Übungen zur Vorlesung Informatik II, Blatt 6 Abgabe: Montag, 05.12.2011, 12.00 Uhr, Informatik

Mehr

Projekt AGB-10 Fremdprojektanalyse

Projekt AGB-10 Fremdprojektanalyse Projekt AGB-10 Fremdprojektanalyse 17. Mai 2010 1 Inhaltsverzeichnis 1 Allgemeines 3 2 Produktübersicht 3 3 Grundsätzliche Struktur und Entwurfsprinzipien für das Gesamtsystem 3 3.1 Die Prefuse Library...............................

Mehr

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben Sichtbarkeit & statische Methoden Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben Nicht sichtbare Methoden Wollen Eltern bestimmte Methoden vor den

Mehr

Computeranwendung und Programmierung (CuP)

Computeranwendung und Programmierung (CuP) Computeranwendung und Programmierung (CuP) VO: Peter Auer (Informationstechnologie) UE: Norbert Seifter (Angewandet Mathematik) Organisatorisches (Vorlesung) Vorlesungszeiten Montag 11:15 12:45 Freitag

Mehr

Vererbung & Schnittstellen in C#

Vererbung & Schnittstellen in C# Vererbung & Schnittstellen in C# Inhaltsübersicht - Vorüberlegung - Vererbung - Schnittstellenklassen - Zusammenfassung 1 Vorüberlegung Wozu benötigt man Vererbung überhaubt? 1.Um Zeit zu sparen! Verwendung

Mehr

UIKit (Cocoa Touch) Framework für ios Apps. Objective C. Model View Controller Pattern

UIKit (Cocoa Touch) Framework für ios Apps. Objective C. Model View Controller Pattern ios Rendering ios Architektur UIKit (Cocoa Touch) A composable, reusable, declarative, real-world inspired animation, and interaction system Framework für ios Apps Objective C Model View Controller Pattern

Mehr

Applet Firewall und Freigabe der Objekte

Applet Firewall und Freigabe der Objekte Hauptseminar Applet Firewall und Freigabe der Objekte Nachweis von Sicherheitseigenschaften für JavaCard Jin Zhou Ein Überblick über diesen Vortrag Applet Firewall Kontext JCRE Entry Point Objekt Shareable

Mehr