I’m having a strange problem using a GLCanvas in an applet. The applet works reasonably well if you leave the mouse pointer still and off of its window. If the mouse pointer is over the applet window, however, the applet starts suffering from sustained freezes (it runs at normal speed for 5-10 seconds, locks up for 5 seconds, and repeats this cycle until the mouse is moved off the applet’s window).
These freezes affect the entire applet, even threads that aren’t directly involved with rendering, but they stop happening if the GLCanvas is removed from the applet. I’ve tried using various “Animator” classes (the default Animator, FPS Animator, and a few I made up), and simply driving the display() method from the applet’s main thread, but the problem remains as long a GLCanvas or GLJPanel is attached to the applet. The problem disappears when I try to duplicate the applet’s behavior with a normal application.
Here’s a simple applet that has the same problem. Can anyone point out what I’m doing to cause it?
Note: This code is based on Kevin Duling’s JOGL port of NeHe tutorial 6.
Test2.java:
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.nio.*;
import javax.imageio.*;
import java.lang.reflect.Array;
import net.java.games.jogl.*;
import net.java.games.jogl.util.*;
import java.awt.*;
import java.applet.*;
import net.java.games.jogl.*;
import net.java.games.jogl.util.*;
public class Test2 extends Applet
{
Animator animator = null;
GLCanvas canvas;
public void init()
{
canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
canvas.addGLEventListener(new Renderer(this));
this.add(canvas);
canvas.setSize(this.getSize().width/2, this.getSize().height/2);
animator = new Animator(canvas);
animator.start();
}
}
Renderer.java
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.nio.*;
import javax.imageio.*;
import java.lang.reflect.Array;
import net.java.games.jogl.*;
import net.java.games.jogl.util.*;
class Renderer
implements GLEventListener
{
private float zrot = 0.0f; // Z Rotation ( NEW )
private Test2 parentApplet;
public Renderer(Test2 parent)
{
parentApplet = parent;
}
/** Called by the drawable to initiate OpenGL rendering by the client.
* After all GLEventListeners have been notified of a display event, the
* drawable will swap its buffers if necessary.
* @param gLDrawable The GLDrawable object.
*/
public void display(GLDrawable gLDrawable)
{
final GL gl = gLDrawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity(); // Reset The View
gl.glTranslatef(0.0f,0.0f,-5.0f);
gl.glRotatef(zrot,0.0f,0.0f,1.0f);
gl.glColor3f(1.0f, 0.0f, 0.0f);
gl.glBegin(GL.GL_QUADS);
// Front Face
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();
zrot+=0.1f;
}
/** Called when the display mode has been changed. <B>!! CURRENTLY UNIMPLEMENTED IN JOGL !!</B>
* @param gLDrawable The GLDrawable object.
* @param modeChanged Indicates if the video mode has changed.
* @param deviceChanged Indicates if the video device has changed.
*/
public void displayChanged(GLDrawable gLDrawable, boolean modeChanged, boolean deviceChanged)
{
}
/** Called by the drawable immediately after the OpenGL context is
* initialized for the first time. Can be used to perform one-time OpenGL
* initialization such as setup of lights and display lists.
* @param gLDrawable The GLDrawable object.
*/
public void init(GLDrawable gLDrawable)
{
final GL gl = gLDrawable.getGL();
gl.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
gl.glClearDepth(1.0f); // Depth Buffer Setup
gl.glEnable(GL.GL_DEPTH_TEST); // Enables Depth Testing
gl.glDepthFunc(GL.GL_LEQUAL); // The Type Of Depth Testing To Do
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // Really Nice Perspective Calculations
}
/** Called by the drawable during the first repaint after the component has
* been resized. The client can update the viewport and view volume of the
* window appropriately, for example by a call to
* GL.glViewport(int, int, int, int); note that for convenience the component
* has already called GL.glViewport(int, int, int, int)(x, y, width, height)
* when this method is called, so the client may not have to do anything in
* this method.
* @param gLDrawable The GLDrawable object.
* @param x The X Coordinate of the viewport rectangle.
* @param y The Y coordinate of the viewport rectanble.
* @param width The new width of the window.
* @param height The new height of the window.
*/
public void reshape(GLDrawable gLDrawable, int x, int y, int width, int height)
{
final GL gl = gLDrawable.getGL();
final GLU glu = gLDrawable.getGLU();
if (height <= 0) // avoid a divide by zero error!
height = 1;
final float h = (float)width / (float)height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, h, 1.0, 20.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
}