Thursday, May 25, 2006

HOWTO: create a first JOGL test

  1. Download the binaries for your platform (the zip with Windows binaries contains a number of DLL's)
  2. Download jogl.jar or jogl.zip
  3. In Eclipse, create a new Java project.
  4. Create a lib folder right under the Project's root, and put the jogl.zip inside.
  5. Point Eclipse to the zip by doing Project Properties->Java Build Path->Libraries->Add Jars...
  6. Put the DLL's somewhere in the project as well. I suggest lib/dll, as I will use this example in step 9.
  7. Create a new class TestRenderer1, copy & paste this source:

    import java.awt.Frame;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    import javax.media.opengl.DebugGL;
    import javax.media.opengl.GL;
    import javax.media.opengl.GLAutoDrawable;
    import javax.media.opengl.GLCanvas;
    import javax.media.opengl.GLEventListener;
    import javax.media.opengl.glu.GLU;

    import com.sun.opengl.util.Animator;

    /**
    * example taken from http://www.javagaming.org/forums/index.php?topic=1474.0
    * Whenever you run this, it's important to have the java.library.path property point to a directory
    * where you put the JOGL dll files, and have the CLASSPATH point to jogl.jar
    */
    public class TestRenderer1 implements GLEventListener {
    public static void main(String[] args) {
    System.out.println("library property = "
    + System.getProperty("java.library.path"));

    Frame frame = new Frame("Triangle Demo");

    GLCanvas canvas = new GLCanvas();
    canvas.requestFocusInWindow();
    canvas.addGLEventListener(new TestRenderer1());

    frame.add(canvas);
    frame.setSize(512, 512);

    final Animator animator = new Animator(canvas);
    frame.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
    new Thread(new Runnable() {
    public void run() {
    animator.stop();
    System.exit(0);
    }
    }).start();
    }
    });
    frame.setVisible(true);
    animator.start();
    }

    public void init(GLAutoDrawable drawable) {
    GL gl = drawable.getGL();

    drawable.setGL(new DebugGL(drawable.getGL()));

    System.out.println("Init GL is " + gl.getClass().getName());
    }

    public void display(GLAutoDrawable drawable) {
    GL gl = drawable.getGL();

    gl.glClear(GL.GL_COLOR_BUFFER_BIT GL.GL_DEPTH_BUFFER_BIT);
    gl.glMatrixMode(GL.GL_MODELVIEW); // Select The Modelview Matrix
    gl.glLoadIdentity(); // Reset The Modelview Matrix

    //this method should not be called in case of ortho projection
    //glu.gluLookAt(0,0,100, 0,0,0, 0,1,0);

    gl.glBegin(GL.GL_TRIANGLES);
    gl.glColor3f(1.0f, 0.0f, 0.0f);
    gl.glVertex3f(0.0f, 0.0f, 0.0f);
    gl.glColor3f(0.0f, 1.0f, 0.0f);
    gl.glVertex3f(100.0f, 0.0f, 0.0f);
    gl.glColor3f(0.0f, 0.0f, 1.0f);
    gl.glVertex3f(100.0f, 100.0f, 0.0f);
    gl.glEnd();
    }

    public void reshape(GLAutoDrawable drawable, int x, int y, int width,
    int height) {

    GL gl = drawable.getGL();
    GLU glu = new GLU();

    System.out.println("reshape to x=" + x + ", y=" + y + ", width="
    + width + ", height=" + height);
    if (height == 0) // Prevent A Divide By Zero By
    {
    height = 1; // Making Height Equal One
    }

    //this is already done by the calling method, according to JOGL documentation
    //gl.glViewport(x,y,width,height); // Reset The Current Viewport

    gl.glMatrixMode(GL.GL_PROJECTION); // Select The Projection Matrix
    gl.glLoadIdentity(); // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    //glu.gluPerspective(90.0f,(double)width/height,0.5f,500.0f);

    //if you want to use Ortho2D projection, be sure to comment out the "gluLookAt" method inside the display() method
    glu.gluOrtho2D(-width / 2, width / 2, -height / 2, height / 2);

    }

    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
    boolean deviceChanged) {
    }

    }


    (sorry for the formatting. Blogspot won't let me paste it in nicely. Anyway, Eclipse will let you reformat if you select everything and press Ctrl+Shift+F)

  8. There will be exactly one syntax error. I don't know why, but the stupid blogspot won't let me put in a vertical bar, or a pipe if you wish. You'll have to manually type that character right before the GL.GL_DEPTH_BUFFER_BIT. Then it should compile.
  9. Create a new "run" item, but for the JVM arguments, be sure to specify
    -Djava.library.path=${project_loc}\lib\dll
  10. Run it. You should see a fancy triangle with all three vertices in a different color

In the beginning ...

A beginning is a very delicate thing ... or so Princess Irula tells us in Dune. I say the beginning is the least delicate thing. It's what comes right after the beginning that usually doesn't survive. I have plenty of beginnings. I begin over and over and over again. This is one of those many beginnings in 3D programming.

This time, I decided to venture into Java, for two reasons: first, I knew the language, and second, I knew the IDE (Eclipse). The fact they were both free didn't hurt, either. However, there is a distinct lack of expertise in Java multimedia or game programming.

I knew of the Java3D API by Sun, but because of the difference with "normal" , goold ol'e OpenGL, I had some difficulties wrapping my head around it. I found some half-ass tutorials, like on JavaWorld, but I didn't see how I could apply the event model and renderloop to a game.

Then I found Killer Programming in Java, which promised to teach my everything I needed for some seriously entertaining games. However, the author is forced to bend over backwards just to get something of a gameloop, where you update the gamestate first, and then render, and then evaluate your speed in order to calculate the frame rate. That's when I tossed Java3D.

The only serious alternative is OpenGL. Both Java and OpenGL promise platform independability, so they actually make a cute couple. They're not married yet, as their bindings still need to be fixed, but JOGL seems like a very mature effort.

And it was much easier to set up than I feared! There's a little magic going on because JOGL uses a few DLL's (or OS'es, or whatever your platform's solution for dynamic linking is), but thanks to a little magic with java.library.path, and some instructions from the JOGL forum, I managed to setup an example really quickly.

(stay tuned for exact instructions :-))