// This code example is created for educational purpose // by Thorsten Thormaehlen (contact: www.thormae.de). // It is distributed without any warranty. import java.awt.*; import java.awt.event.*; import javax.swing.*; import com.jogamp.opengl.*; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.util.FPSAnimator; import com.jogamp.opengl.GL.*; import com.jogamp.opengl.GL2.*; import com.jogamp.opengl.glu.GLU; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; import java.util.Locale; class Renderer { private double[] toyPlaneData; private GLU glu = new GLU(); public float rot1; public float rot2; public float rot3; private void drawTriangle(GL2 gl) { gl.glBegin(GL2.GL_TRIANGLES); gl.glVertex2f(-0.5f, -0.5f); gl.glVertex2f( 0.5f, -0.5f); gl.glVertex2f( 0.0f, 0.5f); gl.glEnd(); } public void init(GLAutoDrawable d) { // read vertex data from file try { int vertSize = 0; File file = new File("ToyPlaneData.txt"); Scanner scanner = new Scanner(file); scanner.useLocale(Locale.US); if(scanner.hasNextInt()) { vertSize = scanner.nextInt(); toyPlaneData = new double[vertSize]; } int i = 0; while (scanner.hasNextDouble()) { double value = scanner.nextDouble(); toyPlaneData[i] = value; i++; } scanner.close(); if(i != vertSize || (vertSize % 3) != 0) toyPlaneData = new double[0]; } catch (FileNotFoundException e) { System.out.println("Can not find vertex data file \"ToyPlaneData.txt\""); } GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glEnable(GL2.GL_DEPTH_TEST); } public void resize(GLAutoDrawable d, int w, int h) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context // ignore this for now gl.glViewport(0, 0, w, h); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective (45.0, (float)w/(float)h, 0.1, 10.0); } public void display(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); // view scene from the side gl.glTranslatef(0.0f,0.0f,-3.0f); gl.glRotatef( -45.0f, 0.0f, 0.0f, 1.0f); gl.glRotatef( -45.0f, 0.0f, 1.0f, 0.0f); gl.glRotatef( 135.0f, 1.0f, 0.0f, 0.0f); // rotate around z gl.glRotatef(rot1, 0.0f, 0.0f, 1.0f); gl.glColor3f(0.0f, 0.0f, 1.0f); drawCoordinateAxisZ(d); // rotate around local y gl.glRotatef(rot2, 0.0f, 1.0f, 0.0f); gl.glColor3f(0.0f, 1.0f, 0.0f); drawCoordinateAxisY(d); // rotate around local x gl.glRotatef(rot3, 1.0f, 0.0f, 0.0f); gl.glColor3f(1.0f, 0.0f, 0.0f); drawCoordinateAxisX(d); // draw the plane in the local coordinate system drawToyPlane(d); } public void dispose(GLAutoDrawable d) {} private void drawCoordinateAxisZ(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glBegin(GL2.GL_LINE_LOOP); // circle in x-y plane for(int a=0; a<360; a+=10) { float angle = (float)Math.PI / 180.0f * a; gl.glVertex3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); } gl.glEnd(); gl.glBegin(GL2.GL_LINES); gl.glVertex3f(0.9f, 0.0f, 0.0f); // x-axis gl.glVertex3f(1.0f, 0.0f, 0.0f); gl.glVertex3f(0.0f, 0.9f, 0.0f); // y-axis gl.glVertex3f(0.0f, 1.0f, 0.0f); gl.glVertex3f(0.0f, 0.0f,-1.0f); // z-axis gl.glVertex3f(0.0f, 0.0f, 1.0f); gl. glEnd(); gl.glBegin(GL2.GL_TRIANGLES); // z-axis tip gl.glVertex3f(0.0f,-0.1f, 0.9f); gl.glVertex3f(0.0f, 0.0f, 1.0f); gl.glVertex3f(0.0f, 0.1f, 0.9f); gl.glEnd(); } private void drawCoordinateAxisX(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glPushMatrix(); gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f); drawCoordinateAxisZ(d); gl.glPopMatrix(); } private void drawCoordinateAxisY(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glPushMatrix(); gl.glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); drawCoordinateAxisZ(d); gl.glPopMatrix(); } private void drawToyPlane(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glColor3f(0.5f, 0.5f, 0.5f); gl.glBegin(GL2.GL_TRIANGLES); for(int i=0; i < toyPlaneData.length; i+=3) { gl.glVertex3d(toyPlaneData[i], toyPlaneData[i+1], toyPlaneData[i+2]); } gl.glEnd(); } } class MyGui extends JFrame implements GLEventListener { private Renderer renderer; public void createGUI() { setTitle("Use 1, 2, and 3 keys to rotate (ALT+key rotates in other direction)"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); GLCanvas canvas = new GLCanvas(caps); setSize(320, 320); getContentPane().add(canvas); final FPSAnimator ani = new FPSAnimator(canvas, 60, true); canvas.addGLEventListener(this); setVisible(true); renderer = new Renderer(); canvas.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent event) { boolean redraw = false; float offset = 2.5f; if (event.isAltDown()) offset = -offset; switch(event.getKeyCode()) { case '1': renderer.rot1 += offset; redraw = true; break; case '2': renderer.rot2 += offset; redraw = true; break; case '3': renderer.rot3 += offset; redraw = true; break; case '0': renderer.rot1 = 0.0f; renderer.rot2 = 0.0f; renderer.rot3 = 0.0f; redraw = true; break; } if(redraw) { setTitle("Yaw " + renderer.rot1 + ", Pitch " + renderer.rot2 + ", Roll " + renderer.rot3); } } }); ani.start(); } @Override public void init(GLAutoDrawable d) { renderer.init(d); } @Override public void reshape(GLAutoDrawable d, int x, int y, int width, int height) { renderer.resize(d, width, height); } @Override public void display(GLAutoDrawable d) { renderer.display(d); } @Override public void dispose(GLAutoDrawable d) { renderer.dispose(d); } } public class GimbalLock { public static void main(String[] args) { System.setProperty("sun.java2d.uiScale", "1.0"); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { MyGui myGUI = new MyGui(); myGUI.createGUI(); } }); } }