22.07.2013 Aufrufe

OpenGL for Java

OpenGL for Java

OpenGL for Java

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>OpenGL</strong> <strong>for</strong> <strong>Java</strong>


Ziele<br />

Bewegte Simulationen grafisch darstellen können<br />

(effizient, realistisch, dreidimensional)<br />

Grundfunktionen von <strong>OpenGL</strong> beherrschen<br />

Mathematische Voraussetzungen für Computer Grafik verstehen


Computer Grafik<br />

Wozu <strong>OpenGL</strong>?<br />

Echtzeit 3D Grafik sehr rechenintensiv<br />

Einfache, leicht parallelisierbare Algorithmen<br />

(wenig Code, wenige Kontrollstrukturen)<br />

Viele wichtige Anwendungen<br />

geeignet für Spezialhardware (Grafikkarte)<br />

Weiterer Vorteil durch Grafik Karte:<br />

Weniger Hauptspeicherzugriffe, indem grafische Objekte<br />

direkt auf der Grafikkarte gespeichert werden.<br />

<strong>OpenGL</strong>: High level Software API für Grafik Hardware


Was ist <strong>OpenGL</strong>?<br />

Spezifikation einer Software Schnittstelle<br />

zur Grafik Hardware (API)<br />

System- und Programmiersprachen unabhängig<br />

ca. 250 Befehle<br />

…und was nicht?<br />

GUI Programmierung, Sound, Netzwerk, usw…


Wie funktioniert‘s?<br />

Benutzerprogramm: Aufruf von <strong>OpenGL</strong> API Funktionen<br />

<strong>OpenGL</strong><br />

Position, Form und Farbe von 3D Objekten (Würfel, Kugel, …)<br />

Position und Farbe von Lichtquellen<br />

Oberflächenbeschaffenheit (Textur) von Objekten<br />

Position und Blickrichtung der Kamera<br />

Koordinatensystem Trans<strong>for</strong>mationen (Drehung, Verschiebung…)<br />

Projektion der 3D Szene auf ein 2D Bild<br />

Farbverlauf auf Flächen (Licht/Schatten)<br />

Sichtbare/verdeckte Flächen<br />

Trans<strong>for</strong>mation von Texturen


Geschichte von <strong>OpenGL</strong><br />

1982 SGI beginnt mit der Entwicklung für<br />

High End Grafik Workstations<br />

1992 <strong>OpenGL</strong> Version 1.0<br />

Seit 1992 Open GL Architecture Review Board (ARB)<br />

Mitglieder: Compaq, ATI, nVidia, HP, IBM, Apple, Microsoft, …<br />

Heute: <strong>OpenGL</strong> Version 2.0<br />

Grafikkarten Wettbewerb, Erweiterungen


GLU (<strong>OpenGL</strong> Utilities)<br />

Zusätzliche Bibliotheken<br />

Einfache Funktionen zum Zeichnen komplexerer Objekte<br />

(Kugeln, Zylinder, Scheibe, …)<br />

Gekrümmte Flächen: NURBS<br />

Viele nützliche Hilfsfunktionen<br />

GLUT (<strong>OpenGL</strong> Utility Toolkit)<br />

Torus, Tetrahedron, Octahedron, …<br />

Text<br />

Platt<strong>for</strong>munabhängige GUI Funktionen (Fenster, Maus, Tastatur)<br />

Für GUI Funktionen verwenden wir <strong>Java</strong>!


GLUT<br />

WGL/GLX/AGL<br />

Window System<br />

Zusätzliche Bibliotheken<br />

Anwendungsprogramm<br />

<strong>OpenGL</strong><br />

Grafik Hardware<br />

GLU<br />

Systemunabhängig<br />

Systemabhängig


GLUT<br />

WGL/GLX/AGL<br />

Window System<br />

Anwendungsprogramm<br />

GL4<strong>Java</strong><br />

<strong>OpenGL</strong><br />

Grafik Hardware<br />

GLU<br />

JNI<br />

Systemunabhängig<br />

Systemabhängig


Canvas3D.java<br />

Das erste <strong>OpenGL</strong> Programm<br />

Starter.java<br />

Fenster erzeugen (JFrame)<br />

Zeichenfläche (Canvas3D) erzeugen und anzeigen<br />

Abgeleitet von GLAnimCanvas (GL4<strong>Java</strong> Klasse)<br />

preInit, init: Initialisierung<br />

display: Wird aufgerufen, um Bildschirm neu zu zeichnen<br />

reshape: Wird aufgerufen, wenn Fenstergröße geändert wird.<br />

Triang


import javax.swing.*;<br />

import java.awt.*;<br />

class Starter<br />

{<br />

public static void main(String[] args)<br />

{<br />

// Erzeugen des <strong>OpenGL</strong> Canvas<br />

Canvas3D canvas3D = new Canvas3D(640,480);<br />

}<br />

}<br />

// Erzeugen des Anwendungsfensters<br />

JFrame frame = new JFrame("Triangles <strong>for</strong> <strong>Java</strong>");<br />

// <strong>OpenGL</strong> Canvas dem Frame hinzufügen<br />

Container pane = frame.getContentPane();<br />

pane.add(canvas3D);<br />

// Frame Grösse setzen und anzeigen<br />

frame.setSize(640,480);<br />

frame.setVisible(true);<br />

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br />

Starter.java


import gl4java.awt.GLCanvas;<br />

class Canvas3D extends GLAnimCanvas<br />

{<br />

// Konstruktor für Gl4<strong>Java</strong> Klasse GLCanvas<br />

public Canvas3D(int w, int h) { super(w, h); }<br />

}<br />

// Globale <strong>OpenGL</strong> Optionen (z.B. double buffering) setzen<br />

public void preInit() { … }<br />

// Einmaliges Initialisieren (z.B. Farbe zum Löschen)<br />

public void init() { … }<br />

// Wird aufgerufen, wenn Bildschirm neu gezeichnet werden muss<br />

public void display() { … }<br />

// Wird aufgerufen, wenn Fenstergröße geändert wird<br />

public void reshape(int width, int height) { … }<br />

Canvas3D.java


eshape(int width, int height)<br />

Bildschirmbereich auf den gezeichnet werden soll in Pixel<br />

glViewport( 0,0,width,height );<br />

Matrix, die 3D nach 2D Projektion macht<br />

Perspektivische Projektion<br />

60 Grad Blickwinkel, Clipping Abstand 2 bis 4<br />

glMatrixMode( GL_PROJECTION );<br />

glLoadIdentity();<br />

gluPerspective(60, 1.0, 2.0, 4.0);<br />

// Matrix, die Zeichenkoordinatensystem positioniert<br />

glMatrixMode( GL_MODELVIEW );<br />

TriangleVie


display<br />

Löschen was zuvor gemalt wurde<br />

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />

Farbe rot einstellen<br />

glColor3f(1.0f,0.0f,0.0f);<br />

Zeichenkoordinatensystem 3 Einheiten nach hinten setzen<br />

glLoadIdentity();<br />

glTranslatef(0.0f, 0.0f, -3.0f);<br />

Dreieck durch Eckpunkte zeichnen<br />

glBegin(GL_TRIANGLES);<br />

glVertex3f(-1.0f, -1.0f, 0.0f); // links unten<br />

glVertex3f( 1.0f, -1.0f, 0.0f); // rechts unten<br />

glVertex3f( 0.0f, 1.0f, 0.0f); // mitte oben<br />

glEnd();


init<br />

Interpolation wenn Eckpunkte unterschiedliche Farbe haben<br />

glShadeModel(GL_FLAT);<br />

Hintergrundfarbe Weiss<br />

glClearColor(1.0f, 1.0f, 1.0f, 0.0f);<br />

preinit<br />

Double Buffering (flüssiger bei bewegter Grafik)<br />

super.doubleBuffer = true;<br />

Für Stereo Brillen<br />

super.stereoView = false;


Schattierungsmodell auf GL_SMOOTH setzen<br />

Jedem Eckpunkt des Dreiecks eine andere Farbe geben<br />

gl.glBegin(GL_TRIANGLES);<br />

gl.glColor3f(1.0f,0.0f,0.0f); rot<br />

gl.glVertex3f(-1.0f, -1.0f, 0.0f); links unten<br />

gl.glColor3f(0.0f,1.0f,0.0f); grün<br />

gl.glVertex3f( 1.0f, -1.0f, 0.0f); rechts unten<br />

gl.glColor3f(0.0f,0.0f,1.0f); blau<br />

gl.glVertex3f( 0.0f, 1.0f, 0.0f); mitte oben<br />

gl.glEnd();<br />

TriangleInterpolatio


Dreieck um 20 Grad um z-Achse nach links drehen<br />

gl.glRotatef( 20.0f, 0.0f, 0.0f, 1.0f );<br />

z-Achse<br />

TriangleRotation, TriangleRotationVie


Matrizen in <strong>OpenGL</strong><br />

Model View Matrix glMatrixMode(GL_MODELVIEW);<br />

Legt Position und Orientierung des Koordinatensystems<br />

fest, in das als nächstes gezeichnet wird.<br />

glRotate(), glTranslate(), …<br />

3D nach 2D Projektions Matrix glMatrixMode(GL_PROJECTION);<br />

Bestimmt, wie eine 3D Szene auf ein 2D Bild projiziert wird.<br />

- Orthogonalprojektion: glOrtho()<br />

- Perspektivische Projektion: gluPerspective(), glFrustum()<br />

Wird i.a. nur einmal gesetzt und nicht mehr geändert.


Koordinatensystem Trans<strong>for</strong>mationen in <strong>OpenGL</strong><br />

glVertex(x,y,z)<br />

Objektkoordinaten<br />

Multiplikation mit Model View Matrix<br />

glRotate(),glTranslate()<br />

Kamerakoordinaten<br />

Multiplikation mit Projektions Matrix<br />

gluPerspective()<br />

2D Koordinaten<br />

Skalieren, Verschieben<br />

glViewPort()<br />

Bildschirmkoordinaten (Pixel)


Etwas Mathematik…<br />

Trans<strong>for</strong>mationen (Translation, Rotation, Projektion)<br />

Koordinatensysteme<br />

Homogene Koordinaten


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_TRIANGLES);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw.<br />

gl.glEnd();<br />

1<br />

2<br />

3<br />

5<br />

4<br />

6


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_POINTS);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

Größe der Punkte<br />

gl.glPointSize(float size)<br />

1<br />

3<br />

2


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_LINES);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

Liniendicke<br />

gl.glLineWidth(float size)<br />

1<br />

4<br />

3<br />

2


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_LINE_STRIP);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

1<br />

4<br />

3<br />

2


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_LINE_LOOP);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

1<br />

4<br />

3<br />

2


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_TRIANGLE_STRIP);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

1<br />

2<br />

3<br />

4 5


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_TRIANGLE_FAN);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

1<br />

2<br />

5<br />

3<br />

4


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_QUADS);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

1<br />

2<br />

6<br />

5<br />

4<br />

3<br />

8<br />

7


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_QUAD_STRIP);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

gl.glVertex(…); Punkt 4<br />

usw. …<br />

gl.glEnd();<br />

1<br />

2<br />

3<br />

6<br />

4<br />

5


<strong>OpenGL</strong> Primitive<br />

gl.glBegin(GL_POLYGON);<br />

gl.glVertex(…); Punkt 1<br />

gl.glVertex(…); Punkt 2<br />

gl.glVertex(…); Punkt 3<br />

usw. …<br />

gl.glEnd();<br />

Ränder dürfen sich nicht schneiden,<br />

sonst ist unklar was innen und außen ist!<br />

Die Eckpunkte müssen alle in einer Ebene liegen,<br />

sonst ist unklar welche Fläche gemalt werden soll!<br />

Polygone müssen konvex sein!<br />

1<br />

2<br />

3<br />

1<br />

5<br />

4<br />

2 3<br />

1<br />

4<br />

5<br />

4<br />

5<br />

2 3


Polygone<br />

GL_TRIANGLES, GL_QUADS, GL_POLYGON<br />

Def. Vorderseite: Reihenfolge der Eckpunkte gegen Uhrzeigersinn<br />

3<br />

3<br />

1 2<br />

Vorderseite<br />

Rückseite<br />

4 3<br />

1 2<br />

1 2<br />

2<br />

4<br />

3<br />

1


Polygone<br />

Polygone gefüllt, als Linien oder nur die Eckpunkte zeichnen<br />

gl.glPolygonMode( GL_FRONT, GL_POINT )<br />

GL_BACK GL_LINE<br />

GL_FRONT_AND_BACK GL_FILL<br />

Nur Vorderseite/Rückseite zeichnen<br />

Effizienz<br />

Verdeckte Flächen bei geschlossenen Körpern<br />

gl.glEnable(GL_CULL_FACE)<br />

gl.glCullFace( GL_FRONT )<br />

GL_BACK<br />

GL_FRONT_AND_BACK


In der init Methode<br />

Geschwindigkeit (Bilder pro Sekunde)<br />

Starten und anhalten<br />

super.start();<br />

super.stop();<br />

Bewegte Grafik<br />

super.setAnimateFps(60.0);<br />

// 60 Aufrufe von display() pro Sekunde


TriangleAnimation, TriangleAnimationVie<br />

Bewegte Grafik<br />

Rotierendes Dreieck um seine (lokale) y-Achse<br />

Vorderseite ausgefüllt, Rückseite Linien


3D Grafik<br />

Problem: Kein „richtiger“ 3D Eindruck wenn Flächen ausgefüllt sind!<br />

Lösung: Licht und Schatten<br />

Lichtquellen<br />

(Position, Richtung, Farbe, Ausbreitung, …)<br />

Oberflächen<br />

(Normalenvektor, Reflektionseigenschaften, Farbe, …)<br />

Cube, CubeLigh


Mehr Mathematik…<br />

Licht Reflektion<br />

Normalenvektoren


ohne Glanz<br />

Diffuse Reflektion…<br />

mit Glanz<br />

CubeLightVie


Normalenvektoren<br />

gl.glBegin(GL_QUADS);<br />

gl.glEnd()<br />

// Vorderseite<br />

gl.glNormal3f( 0.0f, 0.0f, 1.0f);<br />

gl.glVertex3f(-1.0f,-1.0f, 1.0f);<br />

gl.glVertex3f( 1.0f,-1.0f, 1.0f);<br />

gl.glVertex3f( 1.0f, 1.0f, 1.0f);<br />

gl.glVertex3f(-1.0f, 1.0f, 1.0f);<br />

// Rechte Seite<br />

gl.glNormal3f( 1.0f, 0.0f, 0.0f);<br />

gl.glVertex3f( 1.0f,-1.0f, 1.0f);<br />

gl.glVertex3f( 1.0f,-1.0f,-1.0f);<br />

gl.glVertex3f( 1.0f, 1.0f,-1.0f);<br />

gl.glVertex3f( 1.0f, 1.0f, 1.0f);<br />

// usw…


Normalenvektoren<br />

gl.glNormal3f( 0.0f, 0.0f, 1.0f);<br />

Aktuellen Normalenvektor setzen.<br />

Dieser bleibt so lange gültig,<br />

bis ein neuer Normalenvektor gesetzt wird<br />

Möglich: An jedem Eckpunkt ein anderer „Normalenvektor“.<br />

Anwendung: Gekrümmte Flächen, die aus vielen Einzelpolygonen bestehen.<br />

Lichtverlauf an den Kanten dann glatter („smooth shading“).


Licht<br />

// Licht aktivieren<br />

gl.glEnable(GL_LIGHTING);<br />

Ab jetzt Farbberechnung nur noch mit Licht und Oberflächen!<br />

Aufrufe von glColor werden ignoriert!<br />

// Einzelne Lichtquellen einschalten (maximal 8)<br />

gl.glEnable(GL_LIGHT0);<br />

gl.glEnable(GL_LIGHT1);<br />

gl.glEnable(GL_LIGHT2);


Licht<br />

// Position der i-ten Lichtquelle<br />

// Unendlich weit in z-Richtung, daher parallele Strahlen<br />

float[] position = { 0.0f, 0.0f, 1.0f, 0.0f };<br />

gl.glLightfv( i, GL_POSITION, position );<br />

// Farbe der i-ten Lichtquelle (RGBA)<br />

float[] color = { 1.0f, 1.0f, 1.0f, 1.0f }<br />

gl.glLightfv( i, GL_DIFFUSE, color);<br />

GL_AMBIENT<br />

GL_SPECULAR


osition<br />

Licht<br />

(Spotlight)<br />

// Richtung der Lichtstrahlen<br />

float[] direction = { 0.0f, 0.0f, -1.0f }<br />

gl.glLightfv( i, GL_SPOT_DIRECTION, direction );<br />

// Öffnungswinkel der Lichtstrahlen<br />

gl.glLightf( i, GL_SPOT_CUTOFF, angle);<br />

// Exponentielles Abfallen von der Mitte zum Rand<br />

gl.glLightf( i, GL_SPOT_Exponent, exp);<br />

angle<br />

direction


Material<br />

// Reflektionseigenschaften (RGBA)<br />

float[] color = { 1.0f, 0.0f, 0.0f, 1.0 }<br />

gl.glMaterialfv( GL_FRONT, GL_DIFFUSE, color );<br />

GL_BACK GL_AMBIENT<br />

GL_FRONT_AND_BACK GL_SPECULAR<br />

GL_AMBIENT_AND_DIFFUSE<br />

GL_EMISSION<br />

// Glanz (für specular reflection)<br />

gl.glMaterialf( GL_FRONT, GL_SHININESS, factor);<br />

GL_BACK<br />

GL_FRONT_AND_BACK


Material<br />

Weißen, rotierenden Würfel<br />

mit einem roten und einem blauen Spotlight<br />

anstrahlen. Die Lichtquellen drehen sich nicht mit!<br />

Was passiert wenn man backface culling abschaltet?<br />

Würde ein nicht-konvexes Objekt richtig dargestellt?<br />

CubeSpo


Texturen<br />

Idee: Bild auf die Oberflächen von Objekten kleben<br />

1<br />

0<br />

0<br />

1<br />

Texturbild<br />

Polygon<br />

Jedem Eckpunkt des Polygons einen Punkt der Textur zuordnen.<br />

Texturkoordinaten: glTexCoord2f()<br />

Farbwerte innerhalb des Polygons durch Interpolation.


Texturen<br />

import gl4java.utils.textures.PngTextureLoader;<br />

// Texturbild lesen (Abmessungen müssen 2er Potenz sein!)<br />

PngTextureLoader texload = new PngTextureLoader(gl, glu);<br />

texload.readTexture("textures/ambrosil.png");<br />

// Textur in Speicher auf Grafik Karte laden<br />

glTexImage2D( GL_TEXTURE_2D, 0 1 , GL_RGB,<br />

texload.getImageWidth(), texload.getImageHeight(),<br />

0 2 , GL_RGB, GL_UNSIGNED_BYTE, texload.getTexture() );<br />

1 Mip Maps<br />

2 Rand<br />

// Interpolation<br />

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );<br />

GL_TEXTURE_MIN_FILTER GL_NEAREST


Texturen<br />

CubeIntersect<br />

Zwei rotierende Marmorwürfel nebeneinander zeichnen<br />

so dass sie sich überschneiden.<br />

Jeder Würfel dreht sich um eine Achse durch seinen Mittelpunkt!<br />

Würfel zeichnen in eigene Methode kapseln und zweimal aufrufen.<br />

Momentane Matrix auf Stapel speichern bzw. zurück holen:<br />

glPushMatrix, glPopMatrix<br />

Hidden Surface Problem: gl.glEnable(GL_DEPTH_TEST);<br />

z-Puffer Algorithmus<br />

Warum reicht backface culling nicht mehr aus?


GLU Quadrics<br />

Kugel, Zylinder, Scheibe<br />

// Quadric erzeugen bzw. löschen<br />

long quad = glu.gluNewQuadric();<br />

glu.gluDeleteQuadric( quad );<br />

// Kugel<br />

glu.gluSphere( quad, radius, kuchenstücke, stapel );<br />

// Zylinder<br />

glu.gluCylinder( quad, radius_unten, radius_oben,<br />

höhe, kuchenstücke, stapel );<br />

// Scheibe<br />

glu.gluDisk( quad, radius_innen, radius_außen,<br />

kuchenstücke, ringe );


GLU Quadrics<br />

// Darstellung<br />

glu.gluQuadricDrawStyle( quad, GLU_FILL );<br />

GLU_POINT<br />

GLU_LINE<br />

GLU_SHILOUETTE<br />

// Normalenvektoren automatisch erzeugen<br />

glu.gluQuadricNormals( quad, GLU_SMOOTH );<br />

GLU_FLAT<br />

GLU_NONE<br />

// Texturkoordinaten automatisch erzeugen<br />

glu.gluQuadricTexture( quad, GL_TRUE );<br />

GL_FALSE<br />

Quadric


GLU Quadrics<br />

Flat shading statt smooth shading bei der<br />

Berechnung der Normalenvektoren<br />

Mond um Erde kreisen lassen (moon.png)<br />

Texturen in init-Methode laden und auf Grafikkarte speichern<br />

// Platz für ID’s für 2 Texturobjekte<br />

int[] textures = new int[2];<br />

// Texturobjekte erzeugen, ID’s in textures speichern<br />

gl.glGenTextures(2, textures);<br />

// i-te Textur zur aktuellen Textur machen<br />

gl.glBindTexture(GL_TEXTURE_2D, textures[i]);<br />

EarthMoon


Positionierung der Kamera<br />

glu.gluLookAt<br />

(<br />

double eyex, double eyey, double eyez, // Punktvektor<br />

double atx, double aty, double atz, // Punktvektor<br />

double upx, double upy, double upz // Richtungsvektor<br />

);<br />

eye<br />

up<br />

at


Positionierung der Kamera<br />

glu.gluLookAt<br />

(<br />

double eyex, double eyey, double eyez, // Punktvektor<br />

double atx, double aty, double atz, // Punktvektor<br />

double upx, double upy, double upz // Richtungsvektor<br />

);<br />

In „Wirklichkeit“ wird die gesamte Szene bewegt!<br />

Die Kamera steht nach wie vor im Koordinatenursprung<br />

und schaut in negative z-Richtung.<br />

Multiplikation der Model View Matrix mit einer<br />

entsprechenden Matrix von links.<br />

(Trans<strong>for</strong>mation bzgl. Ursprungskoordinatensystem!)<br />

Daher: gluLookAt gleich nach glLoadIdentity aufrufen!


Positionierung der Kamera<br />

Kamera mit Cursor Tasten in x- und y-Richtung bewegen.<br />

Kamera soll dabei immer gerade aus in negative z-Richtung schauen.<br />

import java.awt.event.KeyEvent;<br />

import java.awt.event.KeyListener;<br />

// Klasse Canvas3D ist Key Listener<br />

class Canvas3D extends GLAnimCanvas implements KeyListener<br />

// Im Konstruktor von Canvas3D<br />

addKeyListener(this);<br />

// Callback Funktionen<br />

public void keyTyped(KeyEvent e){}<br />

public void keyReleased(KeyEvent e){}<br />

public void keyPressed(KeyEvent e) { … }


LookAt, LookAtView


Ziel:<br />

3D Objekte mit der Maus anklicken<br />

Problem:<br />

Vorgehen:<br />

Picking & Selection<br />

Verdeckungen (welches Objekt wurde angeklickt?)<br />

Umrechnen von Mauskoordinaten in Weltkoordinaten<br />

Bild intern neu zeichnen, allerdings nur einen ca. 4x4 Pixel<br />

Ausschnitt um die aktuelle Mausposition.<br />

Mitprotokollieren welches Objekt in welcher Tiefe gemalt wurde.<br />

Ergebnisliste (Objekte mit Tiefenin<strong>for</strong>mation) auswerten.<br />

Pic


Picking & Selection<br />

Ausschnitt um die aktuelle Mausposition (x,y) zeichnen.<br />

Dazu PickMatrix links an Projektionsmatrix multiplizieren<br />

// Projektionsmatrix neu berechnen<br />

gl.glLoadIdentity();<br />

glu.gluPickMatrix(x,height-y, 4, 4, viewport);<br />

glu.gluPerspective(60, 1.0,2.0,4.0);<br />

Liste initialisieren, in der die getroffenen Objekte gespeichert werden.<br />

Render Mode auf GL_SELECT setzen.<br />

int[] nameBuffer = new int[100];<br />

gl.glSelectBuffer(100,nameBuffer);<br />

gl.glRenderMode(GL_SELECT);<br />

gl.glInitNames();<br />

gl.glPushName(0);


Picking & Selection<br />

Bild intern neu zeichnen. Objekte durch Zahlen benennen, z.B.<br />

gl.glLoadName(42);<br />

gl.glRectf(-1.0,1.0,-1.0,1.0);<br />

Auf Render Mode GL_RENDER zurückschalten.<br />

int hits = gl.glRenderMode(GL_RENDER);<br />

Für jedes getroffene Objekt enthält nameBuffer nun vier Zahlen:<br />

1<br />

minimale und maximale Tiefe des getroffenen Ausschnitts<br />

Objektname, der während des Zeichnens mit glLoadName gesetzt wurde


Picking & Selection<br />

Projektionsmatrix muss danach wieder hergestellt werden!<br />

Angeklicktes Objekt ist dasjenige mit geringster Tiefe<br />

(nameBuffer durchsuchen!)<br />

Tiefenin<strong>for</strong>mation ist unsigned int. Gibt‘s in <strong>Java</strong> aber nicht!<br />

int<br />

2 30<br />

unsigned int


Picking & Selection<br />

Erde- Mond System erweitern so dass die Planeten<br />

angeklickt werden können.<br />

Angeklickter Planet soll stehen bleiben und sich beim<br />

nächsten Klick weiterbewegen.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!