A detailed look at implementing graphically demanding games in OpenGL with Java, using the JOGL library

Tuesday, December 16, 2008

Starting a new project

So you've reviewed your options for development and chosen Netbeans. Good choice. Once it's installed, fire it up and create a new project from the file menu:

Stick with a standard Java Application and hit next:
Now it's time to choose a name for your project. I always find this a tricky step! Once you've decided, type it in the top box. Stick with the other default settings, and hit Finish.

What do we get?
An empty project that will compile and run, but certainly no flashy spinning OpenGL goodness. For that we need to use the JOGL library that we downloaded in the last post:
  • Right click on Libraries in the project tree up in the top left (ctrl+click, single button mac people) and select Add JAR/Folder...
  • Navigate to where you unzipped the JOGL files, and find lib/gluegen-rt.jar and lib/jogl.jar. You can shift select them to add them both at once. You can also go to Tools->Libraries and set them up as reusable libraries to make it easier to reuse them in other projects, but how much easier can it get?
You'll now be able to write code and even compile it, but if you try and run something that uses gl you'll get an exception: "Exception in thread "main" java.lang.UnsatisfiedLinkError: no jogl in java.library.path"

This is saying in a roundabout way that Java can't find the native implementation files required by the jogl library. To fix it, either follow the instructions on the jogl site to permanently add the libraries to your LD_LIBRARY_PATH or PATH depending on your platform, or set the project configuration to point the JVM in the right place:
  • Go to Build->Set Main Project Configuration->Customize
  • Type -Djava.library.path="/absolute/path/to/jogl/lib" in the VM Options field, including the quotes, but obviously changing the path to the jogl lib directory on your machine.
Now, we can try a very simple OpenGL program. Copy and paste this over the whole of your Main.java:

package tutorial;

import javax.media.opengl.*;
import javax.swing.JFrame;

public class Main {

public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(800, 600);
frame.add(new QuickGL());
frame.setVisible(true);
}

private static class QuickGL extends GLCanvas implements GLEventListener {
public QuickGL() {
super();
addGLEventListener(this);
}
public void display(GLAutoDrawable glD) {
GL gl = glD.getGL();
gl.glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glFlush();
}
public void init(GLAutoDrawable glD) {
}
public void reshape(GLAutoDrawable glD, int arg1, int arg2, int arg3, int arg4) {
}
public void displayChanged(GLAutoDrawable glD, boolean arg1, boolean arg2) {
}
}
}

There's a lot going on there - but lets look piece by piece. First of all, the package tutorial; line just confirms to the compiler that this file is in the tutorial package. You'll have to change that to reflect the name of the game you chose.

Then we have some imports. These are references to libraries and other code that we want to use from within this file. We import the opengl package provided by jogl, and the JFrame class from swing.

Then there are two classes, one within the other. They are nested that way only for convenience, and any non-toy program would have a separate file for QuickGL rather than a static nested class. The Main class has only one method, public static void main(String[] args), which is the 'entry point' for the application. This method creates a JFrame, which is a window, sets the window's size, puts a QuickGL in it, and makes the window visible.

The QuickGL class subclasses GLCanvas and implements GLEventListener. This is about a minimum for an interactive OpenGL program. Subclassing GLCanvas gives us access to all the drawing tools available in OpenGL, and implementing the GLEventListener ensures the correct methods are called to initialise, paint and resize the component. If you are familiar with normal java components, you can think of the display method like the paint method.

In display, we choose a background colour (a medium grey, exciting!) then clear the background with glClear(). Notice the style is very similar to using OpenGL in C - most of the time the only difference in code is the extra gl. object at the beginning of the line. This is because jogl is 99% machine generated from the C OpenGL library.

Finally we call glFlush() to actually perform the drawing. OpenGL has a client/server structure, and most gl commands simply queue up instructions to be executed. glFlush indicates that we're done for the moment and asks the server to do some drawing.

The observant among you may have noticed there's no glSwap call - by default jogl handles this, which is pretty handy given the differences in buffer control between platforms.

The remaining methods satisfy the implementation of the GLEventListener interface. They don't need to do anything yet, so they don't.


So - what do we get at the end of all this?
A grey window! But wait - it's a hardware accelerated, double buffered, 3D capable grey window. Well worth the effort ;o)

You can check out this project with
svn checkout "http://javagamedev.googlecode.com/svn/trunk/Tutorial 1"
or the equivalent for your IDE.

No comments:

Post a Comment