import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; import java.text.*; import java.io.*; import java.util.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; import javax.swing.event.*; import javax.imageio.*; import com.sun.opengl.util.*; import com.jogamp.opengl.util.awt.TextRenderer; import com.jogamp.opengl.util.awt.*; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; public class TestJOGL extends JFrame { // OpenGL Definitionen GL gl; GLU glu; GLCanvas canvas; GLCapabilities capabilities; // Frame mit allen Komponenten public static TestJOGL frame; static JPanel workPanel; static int frameWidth = 800, frameHeight = 600; static int canvasWidth, canvasHeight, portX, portY, portW; static float ARC = (float)Math.PI/180f, DEG = 1f/ARC; static float[] modelMatrix = new float[16]; static boolean showStereo = false, showAxis = false; static WindowListener wndList = new WndList(); static KeyListener keyList = new KeyList(); static MouseListener mouseList= new MouseList(); static float angle, angleStart; static float xLeft = -1.0f, xRight = 1.0f, yBottom = -1.0f, yTop = 1.0f, zNear = 2.5f, zFar = 9999.f; static float eyeX = 0.0f, eyeY = 4.0f, eyeZ = 50.0f, eyeDist = 6.5f, centerX = 0.0f, centerY = 0.0f, centerZ = 0.0f, upX = 0.0f, upY = 1.0f, upZ = 0.0f, transX = 0.0f, transY = 0.0f, transZ = 0.0f, rotateX = 0.0f, rotateY = 0.0f, rotateZ = 0.0f, angleX = 0.0f, angleY = 0.0f, angleZ = 0.0f, deltaX = 0.0f, deltaY = 0.0f, doltaZ = 0.0f, scaleX = 1.0f, scaleY = 1.0f, scaleZ = 1.0f, scaleTotal = 1.0f, rotateVal = 0.0f, rotateAxisHor = 0.0f, rotateAxisVert = 0.0f, rotateAxisZ = 0.0f, rotateAxisVal = 0.0f, xDir = 0.0f, yDir = 0.0f; //================================================================================ // Main-Programm //================================================================================ public static void main(String[] args) throws Exception { System.out.println("TestJOGL Main"); if (args.length > 0) { if (args[0].equals("S")) showStereo = true; } frame = new TestJOGL(); frame.setTitle("TestJOGL"); frame.setSize(frameWidth, frameHeight); frame.setLocation(800, 100); // frame.setLocationRelativeTo(null); // Zentrierung auf dem Bildschirm frame.setVisible(true); // frame.setIconImage(icon3D.getImage()); // frame.setDefaultCloseOperation(EXIT_ON_CLOSE); // Error output umleiten PrintStream console = System.err; File file = new File("err.txt"); FileOutputStream fos = new FileOutputStream(file); PrintStream ps = new PrintStream(fos); System.setErr(ps); } //================================================================================ // TestJOGL Konstruktor, Bereitstellung aller Panels, Einlesen der Daten //================================================================================ TestJOGL() { super(); System.out.println("TestJOGL Konstruktor"); setLayout(new BorderLayout()); // Hauptfenster für die Zeichnungen workPanel = new WorkPanel(); add(workPanel, BorderLayout.CENTER); // Window-Events, insbesondere Close addWindowListener(wndList); } //================================================================================ // Zeichenfläche mit GLCanvas // Hier beginnt die GL-Welt mit Ereignissen im GLEventListener //================================================================================ class WorkPanel extends JPanel implements GLEventListener { WorkPanel() { super(); System.out.println("WorkPanel Konstruktor "+this.toString()); setLayout(new BorderLayout()); // setLayout(null); setBackground(Color.YELLOW); // lightGray); // OpenGL-Canvas capabilities = new GLCapabilities(); capabilities.setStencilBits(32); capabilities.setDoubleBuffered(true); canvas = new GLCanvas(capabilities); canvas.addGLEventListener(this); canvas.addKeyListener(keyList); canvas.addMouseListener(mouseList); canvas.setPreferredSize(new Dimension(0, 0)); System.out.println("Canvas: "+canvas.toString()); try { add((Canvas)canvas); // , BorderLayout.CENTER); } catch (Exception e) { System.out.println("ClassCastException"); e.printStackTrace(); } /*** glu = new GLU(); ***/ // animator = new Animator(canvas); } //============================================================================= // I N I T // OpenGL INIT, Einmalige Initialization der Canvas //============================================================================= public void init(GLAutoDrawable drawable) { // Mit diesem Statement gelangt man immer in die GL-Umgebung // Ganz wichtig! Sonst ist gl zwar definiert, aber steht im Wald gl = drawable.getGL(); System.out.println("GL init "+drawable.toString()); gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); gl.glEnable(GL.GL_DEPTH_TEST); gl.glEnable(GL.GL_LIGHTING); gl.glEnable(GL.GL_LIGHT0); gl.glEnable(GL.GL_LINE_SMOOTH); // gl.glEnable(GL.GL_LINE_STIPPLE); // Versuch der Transparenz (klappt noch nicht) // gl.glEnable(GL.GL_ALPHA_TEST); // gl.glEnable(GL.GL_BLEND); // gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); // Init. Matrix (immer nur Model Matrix) gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadIdentity(); gl.glFrustum(xLeft, xRight, yBottom, yTop, zNear, zFar); showMatrix(gl.GL_MODELVIEW_MATRIX, "Model Matrix nach glFrustum"); } //============================================================================= // D I S P L A Y // OpenGL DISPLAY (entspricht etwa paintComponent in der Nicht-GL-Welt) //============================================================================= public void display(GLAutoDrawable drawable) { } public void displayX(GLAutoDrawable drawable) { int w, h, col; byte stencilIndex; // View anpassen gl.glPushMatrix(); // Grundzustand Frustum retten /*** glu.gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); ***/ showMatrix(gl.GL_MODELVIEW_MATRIX, "Model Matrix nach gluLookAt"); gl.glClearStencil(0); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); // Vorbereitung für Viewport (Werte n i c h t identisch mit glFrustum !!!) portW = canvasWidth; if (portW > canvasHeight) portW = canvasHeight; portY = (canvasHeight - portW) / 2; // Stereodarstellung: Zwei Bilder if (showStereo) { // Rechtes Bild (Schielblick für das l i n k e Auge) gl.glPushMatrix(); glu.gluLookAt(eyeX-eyeDist/2f, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); portX = canvasWidth/2; gl.glViewport(portX, portY, portW, portW); // gl.glRotatef(+eyeDist/2/eyeZ*DEG, 0, 1, 0); displayComponentPicture(gl); gl.glPopMatrix(); // Linkes Bild (Schielblick für das r e c h t e Auge) gl.glPushMatrix(); glu.gluLookAt(eyeX+eyeDist/2f, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); portX = canvasWidth/2 - portW; gl.glViewport(portX, portY, portW, portW); // gl.glRotatef(-eyeDist/2/eyeZ*DEG, 0, 1, 0); displayComponentPicture(gl); gl.glPopMatrix(); } // Monodarstellung mit einem Bild else { glu.gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); portX = (canvasWidth - portW) / 2; gl.glViewport(portX, portY, portW, portW); displayComponentPicture(gl); } gl.glPopMatrix(); // Frustum wiederherstellen } // Gemeinsame Routine für Display im Stereo- und Mono-Modus, // wird im Stereo-Modus zweimal aufgerufen void displayComponentPicture (GL gl) { float[] v1 = {-8f, -8f, -8f}; float[] v2 = {+8f, -8f, -8f}; float[] v3 = {-8f, +8f, -8f}; float[] v4 = {+8f, +8f, -8f}; float[] v5 = {-8f, -8f, +8f}; float[] v6 = {+8f, -8f, +8f}; float[] v7 = {-8f, +8f, +8f}; float[] v8 = {+8f, +8f, +8f}; drawLine(gl, v1, v2, 2f, 0xff0000ff); drawLine(gl, v3, v4, 2f, 0xff0000ff); drawLine(gl, v1, v3, 2f, 0xff0000ff); drawLine(gl, v2, v4, 2f, 0xff0000ff); drawLine(gl, v5, v6, 2f, 0xffff0000); drawLine(gl, v7, v8, 2f, 0xffff0000); drawLine(gl, v5, v7, 2f, 0xffff0000); drawLine(gl, v6, v8, 2f, 0xffff0000); drawLine(gl, v1, v5, 2f, 0xff00ff00); drawLine(gl, v2, v6, 2f, 0xff00ff00); drawLine(gl, v3, v7, 2f, 0xff00ff00); drawLine(gl, v4, v8, 2f, 0xff00ff00); float[] k1 = { -8f, 0f, 0f}; float[] k2 = { +8f, 0f, 0f}; drawLine(gl, k1, k2, 1f, 0xff000000); float[] k3 = { 0f, -8f, 0f}; float[] k4 = { 0f, +8f, 0f}; drawLine(gl, k3, k4, 1f, 0xff000000); float[] k5 = { 0f, 0f, -8f}; float[] k6 = { 0f, 0f, +8f}; drawLine(gl, k5, k6, 1f, 0xff000000); // Interne Transformation // transform(gl); // workPanel.repaint(); } //============================================================================= // R E S H A P E // OpenGL RESHAPE, entspricht etwa WindowEvent resize //============================================================================= public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { // Verhinderung divide by zero if (h == 0) h = 1; // Ermittlung Größe und Position der Canvas if (showStereo) { if (w > 2*h) { canvasWidth = 2*h; canvasHeight = h; } else { canvasWidth = w; canvasHeight = w/2; } } else { if (w > h) { canvasWidth = h; canvasHeight = h; } else { canvasWidth = w; canvasHeight = w; } } canvas.setSize(canvasWidth, canvasHeight); canvas.setLocation((w-canvasWidth)/2, (h-canvasHeight)/2); } // Dummy public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} //================================================================================ // Herkömmliche Grafik //================================================================================ /***** public void paintComponent(Graphics g) { System.out.println("paintComponent "+g.toString()); g.setColor(Color.BLUE); g.drawLine(10, 10, 800, 500); } ****/ } //================================================================================ // Hier endet der GL-Kontext. // Alle Routinen außerhalb müssen immer mit GL als Parameter aufgerufen werden //================================================================================ //============================================================================= // Zentralroutine zum Zeichnen einer Linie //============================================================================= void drawLine(GL gl, float[] v1, float[] v2, float size, int col) { // System.out.format("drawLine %6.1f %6.1f %6.1f --> %6.1f %6.1f %6.1f %4.1f %8x %n", // v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], size, col); gl.glLineWidth(size); setGLColor(gl, col, false); gl.glBegin(gl.GL_LINES); gl.glVertex3i((int)v1[0], (int)v1[1], (int)v1[2]); gl.glVertex3i((int)v2[0], (int)v2[1], (int)v2[2]); gl.glEnd(); } //================================================================================ // Allg. Transformation der model matrix //================================================================================ void transform(GL gl) { } //================================================================================ // Rotation um eine beliebige Achse //================================================================================ void rotateAxis(GL gl, float rotVal, float rotHor, float rotVert, float rotZ) { } //================================================================================ // Multiplikation zweier Matrizen (links l*m, rechts m*n, beide in linearer Form) //================================================================================ public static float[] matMult(float[] mat1, float[] mat2, int dim) { int row, col, n, x, y, i; // dim ist die gemeinsame Kante der Matrizen, // row und col werden aus der tatsächlichen Länge bestimmt row = mat1.length / dim; col = mat2.length / dim; float[] result = new float[row*col]; for (n=0; n 2) i1 = 0; i2 = i - 1; if (i2 < 0) i2 = 2; result[i] = v1[i1]*v2[i2] - v1[i2]*v2[i1]; } return result; } //================================================================================ // Event-Handler //================================================================================ //================================================================================ // Key Events //================================================================================ static class KeyList implements KeyListener { public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) {}; public void keyTyped(KeyEvent e) {} } //================================================================================ // Mouse Events //================================================================================ static class MouseList implements MouseListener { public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } } //================================================================================ // Action events allgemein (egal ob aus Menu oder Buttons) //================================================================================ public class ActList implements ActionListener { public void actionPerformed(ActionEvent e) { // Auslösen GLEvent display // if (repaintFlag) canvas.repaint(); } } //================================================================================ // Reaktion auf Window events //================================================================================ static class WndList extends WindowAdapter { public void windowClosing(WindowEvent e) { String source = e.getSource().toString(); int i = source.indexOf("title="); System.out.println("Window close"); System.exit(0); } } //================================================================================ // Trace-Hilfe: Ausgabe der Projektions- bzw. Modellmatrix (GL) //================================================================================ void showMatrix(int modus, String comment) { gl.glGetFloatv(modus, modelMatrix, 0); showMatrix(modelMatrix, comment); // andere Signatur (typischer Polymorphismus) } //================================================================================ // Ausgabe einer beliebigen 4x4-Matrix (auch außerhalb von GL) //================================================================================ void showMatrix(float[] mat, String comment) { System.out.println(comment); System.out.format(" %8.3f %8.3f %8.3f %8.3f %n", mat[0], mat[4], mat[8], mat[12]); System.out.format(" %8.3f %8.3f %8.3f %8.3f %n", mat[1], mat[5], mat[9], mat[13]); System.out.format(" %8.3f %8.3f %8.3f %8.3f %n", mat[2], mat[6], mat[10], mat[14]); System.out.format(" %8.3f %8.3f %8.3f %8.3f %n", mat[3], mat[7], mat[11], mat[15]); } //================================================================================ // Timer-Prozedur en //================================================================================ class TimerProcAni implements ActionListener { public void actionPerformed(ActionEvent e) { } } //============================================================================= // Farbe und ggf. Beleuchtungsmodus festlegen //============================================================================= void setGLColor(GL gl, int col, boolean lighting) { float[] diffuse = {0.5f, 0.5f, 0.5f, 0.0f}; float[] ambient = {0.5f, 0.5f, 0.5f, 0.0f}; float[] material = {0.0f, 0.0f, 0.0f, 1.0f}; float[] position = {3.0f, 2.0f, 5.0f, 0.0f}; GLColor c3; // System.out.println("SetGLColor: "+col+" "+lighting); if (lighting) { gl.glEnable(GL.GL_LIGHTING); gl.glEnable(GL.GL_LIGHT0); } else gl.glDisable(gl.GL_LIGHTING); c3 = new GLColor(col); gl.glColor4f(c3.red, c3.green, c3.blue, c3.alpha); gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0); material[0] = c3.red; material[1] = c3.green; material[2] = c3.blue; gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, material, 0); // gl.glDisable(gl.GL_LIGHTING); } //================================================================================ // Color-Aufbereitung: Integer -> RGB-Komponenten //================================================================================ class GLColor { float alpha; float red; float green; float blue; GLColor(int col) { alpha = (float)(((col & 0xff000000) >> 24)/255.0f); red = (float)(((col & 0x00ff0000) >> 16)/255.0f); green = (float)(((col & 0x0000ff00) >> 8)/255.0f); blue = (float) ((col & 0x000000ff)/255.0f); } } /****** INT-Variante class GLColor { int alpha; int red; int green; int blue; GLColor(int col) { alpha = (col & 0xff000000) >> 24; red = (col & 0x00ff0000) >> 16; green = (col & 0x0000ff00) >> 8; blue = (col & 0x000000ff); } } ***/ }