/** * Unterricht #3 - Projektionen, Transformationen und Steuerung über Maus und Tastatur */ package cg; import java.awt.Frame; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.util.FPSAnimator; /** * @author tavkhelidze * */ /* Tastenkontrolle: *************** Kamera/Auge/Betrachter *******************: [c] - setzt die Kamera komplett (d.h. Ihre Richtung und Position) zurück [Pfeil oben] - Bewegung vorwärts [Pfeil unten] - Bewegung rückwärts [Pfeil links] - Bewegung links [Pfeil rechts] - Bewegung rechts [Bild auf] - Bewegung oben [Bild ab] - Bewegung unten [a] - Rotation nach links [d] - Rotation nach rechts [w] - Rotation nach oben [s] - Rotation nach unten */ public class Main implements GLEventListener, KeyListener, MouseListener, MouseMotionListener { //setting frame size inputs static int width = 800; static int height = 600; static GLU glu = new GLU(); static float x = 0f; float rotat = 0f; float trans = 0f; // camera position (x, y, z coordinates) static float camera_position[] = {-1f, 1.0f, 1.0f}; // camera orientation (x, y, z coordinates) static float camera_orientation[] = {0f, 0.0f, 0}; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub /* -------------------- OpenGL context -------------------*/ //instantiating OpenGL functionality final GLProfile profile = GLProfile.get(GLProfile.GL2); GLCapabilities capabilities = new GLCapabilities(profile); //creating canvas and attaching the listeners for OpenGL-Events to it final GLCanvas glcanvas = new GLCanvas(capabilities); glcanvas.addGLEventListener(new Main()); glcanvas.addKeyListener(new Main()); glcanvas.addMouseListener(new Main()); glcanvas.addMouseMotionListener(new Main()); /* -------------------- FRAME -------------------*/ //creating frame final Frame frame = new Frame ("AWT OpenGL-Fenster"); //setting visibility and sizes to frame: frame.setSize(width, height); frame.setVisible(true); //adding canvas to frame frame.add(glcanvas); //adding Window-events Listener to the frame frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent arg0) { System.exit(0); } }); // The animator final FPSAnimator animator = new FPSAnimator(glcanvas, 60,true); animator.start(); } @Override public void init(GLAutoDrawable drawable) { // TODO Auto-generated method stub GL2 gl = drawable.getGL().getGL2(); //Mit diesem Befehl setzt sich eine andere Farbe (mit Gleitkommazahlen als Parameter,die dem RGBA-Format entsprechen) gl.glClearColor(0.000f, 0.749f, 1.000f, 1.0f); //Mit diesem Befehl wird der Tiefentest aktiviert - damit vermeidet man das Zeichnen von Flächen, die sich hinter anderen Flächen befinden gl.glEnable(GL2.GL_DEPTH_TEST); } @Override public void dispose(GLAutoDrawable drawable) { // TODO Auto-generated method stub } @Override public void display(GLAutoDrawable drawable) { // TODO Auto-generated method stub GL2 gl = drawable.getGL().getGL2(); gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); // setzt die ModelView-Matrix als aktuelle Matrix, mit der es im Moment (zwecks Transformationen) gearbeitet wird gl.glMatrixMode(GL2.GL_MODELVIEW); // ersetzt die aktuelle Matrix durch die Einheitsmatrix gl.glLoadIdentity(); // setzt die Kamera in Szene glu.gluLookAt(camera_position[0], camera_position[1], camera_position[2], camera_orientation[0], camera_orientation[1], camera_orientation[2], 0f, 1f, 0f); // legt die aktuelle Matrix auf den aktuellen Stack (Stapel) - in diesem Beispiel ist es der ModelView-Stapel gl.glPushMatrix(); // multipliziert die aktuelle Matrix mit der Translationsmatrix zwecks Verschiebung gl.glTranslatef( 0.0f, 0.0f, -3.0f - trans ); // Verschiebung des Tetraeders immer weiter (mit jedem Animationsschritt) in die Tiefe des Fensters // multipliziert die aktuelle Matrix mit der Rotationssmatrix zwecks Drehung gl.glRotatef( rotat, 0f, 1.0f, 0f ); // Drehung des Tetraeders um rotat Grad um Y-Achse bei jedem Animationsschritt // multipliziert die aktuelle Matrix mit der Skalierungsmatrix zwecks Deformation (in diesem Beispiel - gleichmäßiger Vergrößerung) gl.glScalef( 1.1f, 1.1f, 1.1f ); // ------ zeichnet den definierten (siehe unten) Tetraeder (wird schrittweise animiert) ------ animTetrahedron(gl); //ersetzt die aktuelle Matrix durch die erste (oberste) Matrix des aktuellen Stapels und löscht diese Matrix aus dem Stapel // dieser Befehl wird vor dem Zeichnen eines weiteren Objekts verwendet //gl.glPopMatrix(); // Inkrementierung einiger Variablen zwecks Animation if (x<0.5f) {x +=0.005;} else {x =0f;}; rotat +=0.2f; trans +=0.01f; } /** * When the window changes its position or shape the projection transformation * and viewport dimensions have to be adjusted accordingly. */ @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { // TODO Auto-generated method stub final GL2 gl = drawable.getGL().getGL2(); float h = (float) width / (float) height; //bestimmt die Grenzen des Schaufensters (man kann diesen Befehl unter display-Methode mehrfach einsetzen, um das Fenster für die unterschiedlichen Projektionen zu unterteilen) gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); //setzt die perspektivische Projektion der 3D-Szene auf 2D-Bildschirm glu.gluPerspective(45.0f, h, 1, 20.0); //setzt die orthogonale Projektion (Parallel-Projektion) der 3D-Szene auf 2D-Bildschirm (schaltet OpenGL praktisch in einen 2D-Modus) //gl.glOrtho(-5, 5, -5, 5, 0, 20); } // ------ beschreibt einen dynamischen Tetraeder (zwecks Animation) ------ void animTetrahedron(GL2 gl) { gl.glBegin(GL2.GL_TRIANGLES); // erste Seitenfläche gl.glColor3f( 0.7f, 0.0f, 0.0f ); // Red gl.glVertex3f( 0.7f, 1.0f+x, 0.0f ); // Top gl.glColor3f( 0.0f, 0.7f, 0.0f ); // Green gl.glVertex3f( -0.7f, -0.7f, 0.7f ); // Left gl.glColor3f( 0.0f, 0.0f, 0.7f ); // Blue gl.glVertex3f( 0.7f, -0.7f, 0.7f ); // Right // zweite Seitenfläche gl.glColor3f( 0.7f, 0.0f, 0.0f ); // Red gl.glVertex3f( 0.7f, 1.0f+x, 0.0f ); // Top gl.glColor3f( 0.0f, 0.0f, 0.7f ); // Blue gl.glVertex3f( 0.7f, -0.7f, 0.7f ); // Left gl.glColor3f( 0.0f, 0.7f, 0.0f ); // Green gl.glVertex3f( 0.7f, -0.7f, -0.7f ); // Right // dritte Seitenfläche gl.glColor3f( 0.7f, 0.0f, 0.0f ); // Red gl.glVertex3f( 0.7f, 1.0f+x, 0.0f ); // Top gl.glColor3f( 0.0f, 0.7f, 0.0f ); // Green gl.glVertex3f( 0.7f, -0.7f, 0.7f ); // Left gl.glColor3f( 0.0f, 0.0f, 0.7f ); // Blue gl.glVertex3f( 0.7f, -0.7f, -0.7f ); // Right // GrundFläche gl.glColor3f( 0.0f, 0.7f, 0.0f ); // Red gl.glVertex3f( -0.7f, -0.7f, 0.7f ); // Top gl.glColor3f( 0.0f, 0.0f, 0.7f ); // Blue gl.glVertex3f( 0.7f, -0.7f, 0.7f ); // Left gl.glColor3f( 0.0f, 0.7f, 0.0f ); // Green gl.glVertex3f( 0.7f, -0.7f, -0.7f ); // Right gl.glEnd(); } // Ereignis: der Mauszeiger wird gedrückt gezogen @Override public void mouseDragged(MouseEvent e) { // halten Sie den Mauszeiger über Methode getWhen() um die Beschreibung dieser Methode zu bekommen - checkt auch die anderen Methoden der MouseEvent-Klasse System.out.println("Mouse dragged: " + e.getWhen()); } // Ereignis: der Mauszeiger wird bewegt @Override public void mouseMoved(MouseEvent e) { // gibt den String "Mouse moved: true" auf der Konsole aus, wenn Ihre Maus bei gedrückter Umschalttaste gezogen wird System.out.println("Mouse moved: " + e.isShiftDown()); } // Ereignis: Maustaste geklickt (also erstmal gedrückt und danach auch losgelassen) @Override public void mouseClicked(MouseEvent e) { // gibt den String mit der Anzahl von Klicks auf der Konsole aus System.out.println("Mouse released;" + "\n" + "# of clicks: " + e.getClickCount()+ "\n"); } // Ereignis: Maustaste gedrückt @Override public void mousePressed(MouseEvent e) { // halten Sie den Mauszeiger über Methode getPoint() um die Beschreibung dieser Methode zu bekommen - checkt auch die anderen Methoden der MouseEvent-Klasse System.out.println("Mouse pressed: " + e.getPoint()); } // Ereignis: Maustaste losgelassen @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // gibt einen String mit X-Koordinaten Ihres Mauszeigers auf der Konsole aus, wenn Ihre Maus den Leinwand-Bereich betritt (getXOnScreen() - auf dem Bildschirm, getX() - auf dem Schaufenster) System.out.println("Mouse entered: "+ "\n" + "X on screen: " + e.getXOnScreen()+ "\n" + "X: " + e.getX()); } @Override public void mouseExited(MouseEvent e) { // gibt einen String mit Y-Koordinaten Ihres Mauszeigers auf der Konsole aus, wenn Ihre Maus den Leinwand-Bereich verlässt (getXOnScreen() - auf dem Bildschirm, getX() - auf dem Schaufenster) System.out.println("Mouse exited: "+ "\n" + "X on screen: " + e.getYOnScreen()+ "\n" + "X: " + e.getY()); } // Ereignis: Tastaturtaste getippt (erst gedrückt und danach losgelassen) @Override public void keyTyped(KeyEvent e) { // halten Sie den Mauszeiger über Methode getKeyCode() um die Beschreibung dieser Methode zu bekommen - checkt auch die anderen Methoden der KeyEvent-Klasse, zB - getKeyChar() [Codes für die anderen Tasten könnt ihr beispielsweise auf der Webseite https://www.ascii-codes.com/ abrufen] int keyCo = e.getKeyCode(); // Konstante VK_A steht für die Tastaturtaste A if (keyCo == KeyEvent.VK_A) { System.out.println("typed " + e.getKeyChar() + " button"); } } // Ereignis: Tastaturtaste gedrückt @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); // Konstante VK_DOWN steht für die Tastaturtaste [Pfeil unten] if (keyCode == KeyEvent.VK_DOWN) { // halten Sie den Mauszeiger über Methode getID() um die Beschreibung dieser Methode zu bekommen System.out.println("pressed " + e.getID() + " button"); } // reset the camera position and orientation // Konstante VK_C steht für die Tastaturtaste C else if (keyCode == KeyEvent.VK_C) { camera_position[0] = -1.0f; camera_position[1] = 1.0f; camera_position[2] = 1.0f; camera_orientation[0] = 0.0f; camera_orientation[1] = 0.0f; camera_orientation[2] = 0.0f; } } // Ereignis: Tastaturtaste losgelassen @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } }