// 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.util.Random; class Renderer { private GLU glu = new GLU(); private int width = 0; private int height = 0; private float[] randVals = new float[1000]; public float t = 1.0f; public float d0 = 3.0f; public void init(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glEnable(GL2.GL_DEPTH_TEST); Random generator = new Random(); // create random values between -1.0 and 1.0 for(int r=0; r < randVals.length; r++) { double rval = generator.nextDouble(); randVals[r] = ((float)(2.0 * rval - 1.0)); } } 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); width = w; height = h; } 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_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective (dollyZoomFovy(), (float)width/(float)height, 0.1, 50.0); gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); // translate camera by 3 units gl.glTranslatef(0.0f, 0.0f, -t*d0); // draw a cube in the local coordinate system drawCube(d); // draw random lines drawRandomLines(d); } public float dollyZoomFovy() { double fovyInit = 60.0; // initial field of view double theta = fovyInit / 180.0 * Math.PI; // degree to rad double f = 1.0f / Math.tan(theta/2.0f); double fNew = f * (d0*t-1) / (d0-1); double thetaNew = Math.atan(1.0f / fNew) * 2.0; double val = 180.0 * thetaNew / Math.PI; //rad to degree return (float) val; } private void drawCube(GLAutoDrawable d ) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context gl.glColor3f(1.0f, 1.0f, 1.0f); gl.glLineWidth(3.0f); gl.glBegin(GL2.GL_LINE_LOOP); gl.glVertex3f(-1.0f, 1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); gl.glVertex3f( 1.0f,-1.0f, 1.0f); gl.glVertex3f(-1.0f,-1.0f, 1.0f); gl.glEnd(); gl.glBegin(GL2.GL_LINE_LOOP); gl.glVertex3f(-1.0f, 1.0f,-1.0f); gl.glVertex3f( 1.0f, 1.0f,-1.0f); gl.glVertex3f( 1.0f,-1.0f,-1.0f); gl.glVertex3f(-1.0f,-1.0f,-1.0f); gl.glEnd(); gl.glBegin(GL2.GL_LINE_LOOP); gl.glVertex3f( 1.0f, 1.0f,-1.0f); gl. glVertex3f( 1.0f, 1.0f, 1.0f); gl.glVertex3f( 1.0f,-1.0f, 1.0f); gl.glVertex3f( 1.0f,-1.0f,-1.0f); gl.glEnd(); gl.glBegin(GL2.GL_LINE_LOOP); gl.glVertex3f(-1.0f, 1.0f,-1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); gl.glVertex3f(-1.0f,-1.0f, 1.0f); gl.glVertex3f(-1.0f,-1.0f,-1.0f); gl.glEnd(); gl.glLineWidth(1.0f); } private void drawRandomLines(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); // get the OpenGL 2 graphics context if(randVals.length % 5 != 0) return; int i = 0; while(i < randVals.length) { gl.glColor3d(Math.abs(randVals[i++]), Math.abs(randVals[i++]), Math.abs(randVals[i++])); float x = randVals[i++]; float y = randVals[i++]; gl.glBegin(GL2.GL_LINES); gl.glVertex3f(x, y, -1.0f); gl.glVertex3f(x, y, 1.0f); gl.glEnd(); } } } class MyGui extends JFrame implements GLEventListener { private Renderer renderer; public void createGUI() { setTitle("Use the 1 key to perform a dolly zoom"); 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 < 1.0f) renderer.t = 4.0f; if(renderer.t > 4.0f) renderer.t = 1.0f; redraw = true; break; case '0': renderer.t = 1.0f; redraw = true; break; } if(redraw) { float distance = renderer.t*renderer.d0; float fovy = renderer.dollyZoomFovy(); setTitle("Distance: " + distance + " FieldofView: " + fovy); } } }); 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) { } } public class DollyZoom { public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { MyGui myGUI = new MyGui(); myGUI.createGUI(); } }); } }