// 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.nio.FloatBuffer; class Renderer { private GLU glu = new GLU(); public float t; 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) { 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); if(true) { // interpolate rotation matrices, which is wrong FloatBuffer r0 = FloatBuffer.allocate(16); FloatBuffer r1 = FloatBuffer.allocate(16); FloatBuffer rt = FloatBuffer.allocate(16); gl.glPushMatrix(); // save for later use gl.glLoadIdentity(); gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, r0); // rotate around z gl.glRotatef(180.0f, 0.0f, 0.0f, 1.0f); gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, r1); gl.glPopMatrix(); // restore //interpolate for(int i=0; i < 16; i++) { rt.array()[i] = ( (1-t) * r0.array()[i] + t * r1.array()[i] ); } gl.glMultMatrixf(rt); }else{ // interpolate rotation angle, which is correct // rotate around z gl.glRotatef(t*180.0f, 0.0f, 0.0f, 1.0f); } // draw coordinate system gl.glColor3f(0.0f, 0.0f, 1.0f); drawCoordinateAxisZ(d); gl.glColor3f(0.0f, 1.0f, 0.0f); drawCoordinateAxisY(d); gl.glColor3f(1.0f, 0.0f, 0.0f); drawCoordinateAxisX(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(); } } class MyGui extends JFrame implements GLEventListener { private Renderer renderer; public void createGUI() { setTitle("Use the 1 key to interpolate rotation"); 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 = 0.02f; if (event.isAltDown()) offset = -offset; switch(event.getKeyCode()) { case '1': renderer.t += offset; if(renderer.t < 0.0f) renderer.t = 1.0f; if(renderer.t > 1.0f) renderer.t = 0.0f; redraw = true; break; } if(redraw) { setTitle("Time " + renderer.t); } } }); 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 RotationInterpolation { 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(); } }); } }