Open source Java projects: Java Binding for OpenGL (JOGL)

A low-level Java API for 3D graphics

1 2 3 4 5 6 7 8 9 Page 4
Page 4 of 9

Working with GLCanvas

GLCanvas takes advantage of hardware acceleration to perform OpenGL operations rapidly. You can employ this drawable in AWT and Swing GUIs, but must exercise care when using GLCanvas with Swing. For example, when adding a GLCanvas to a JFrame that also contains lightweight components, you must add this drawable to a JPanel, and then add the panel to the frame.

Listing 1 presents the source code to a JOGLDemo1 application that shows you how to architect a Swing-based JOGL program with GLCanvas and GLEventListener.

Listing 1. JOGLDemo1.java

// JOGLDemo1.java

// This demo renders a smoothly shaded triangle and a flat shaded square. The
// triangle is rendered in front of the square in the default front view --
// looking toward the negative Z axis. In the back view (looking toward the
// positive Z axis), as specified by a command-line argument, the square is
// rendered in front of the triangle.

import java.awt.*;

import javax.media.opengl.*;
import javax.media.opengl.glu.*;

import javax.swing.*;

public class JOGLDemo1 extends JFrame

...

Download the complete Listing 1.

Listing 1 specifies classes JOGLDemo1 and SceneRenderer. The former class provides the application's entry point, which lets you decide whether to view the rendered scene -- a smoothly shaded triangle and a flat shaded square -- from the front (the default) or the back (if back is specified as the single command-line argument). The latter class renders the scene.

After determining the scene's viewing direction, the main() method's initial thread hands off GUI construction to the event-dispatching thread. This thread creates a SceneRenderer component instance, informing the instance of the viewing direction. The thread next sizes this component and adds it to the JFrame.

SceneRenderer subclasses GLCanvas and implements GLEventListener. As a result, this component is both a drawable and a listener for events arising from the underlying JOGL/OpenGL implementation. The first event results in the init() method being invoked, which takes care of initialization.

After printing a console message to show you that it's always called first, init() invokes its drawable argument's public GL getGL() method to access the rendering pipeline. The returned javax.media.opengl.GL instance is used to enable depth buffer testing, to ensure that the square is not rendered in front of the triangle when the scene is viewed from the front.

Be careful with getGL()

Don't invoke the getGL() method outside of a listener method because getGL() might return null in this situation. Also, instead of caching the returned GL instance, always re-obtain this instance via a fresh call to getGL() at the start of the listener method. According to JOGL's user guide: "multithreading issues inherent to the AWT toolkit make it difficult to reason about which threads certain operations are occurring on, and if the GL object is stored in a field it is unfortunately too easy to accidentally make OpenGL calls from a thread that does not have a current context. This will usually cause the application to crash."

The next event method to be invoked is reshape(). (In addition to being invoked immediately after init(), reshape() is invoked whenever the drawable is resized.) Although I could use this method to create a viewport, I prefer the default viewport (covering the whole surface) that JOGL creates prior to invoking this method.

More importantly, reshape() is the place to initialize the projection matrix, which determines how the scene is projected onto the screen: orthographic or perspective. If I was projecting an architectural drawing, I'd choose an orthographic projection. However, because I want to take advantage of perspective, I've decided to go with a perspective projection, by invoking the following GL method:

public void glFrustum(double left, double right, double bottom, double top, 
                      double near_val, double far_val)
  • left and right contain the coordinates for the left and right vertical clipping planes
  • bottom and top contain the coordinates for the bottom and top horizontal clipping planes
  • zNear and zFar contain the positive distances from the viewpoint (the location where the viewer is observing the scene) to the near and far clipping planes
Related:
1 2 3 4 5 6 7 8 9 Page 4
Page 4 of 9