Annoying flicker

I’m new to opengl and to JOGL so I’m trying to learn from the opengl superbible. This program is drawing a 3d plane and rotating it around the y axis. The camera stays still and I get a ton of flicker no matter how slowly it rotates. I have depth testing enabled and I have doubleBuffering enabled but I still have peices, like the tail fin, being displayed behind objects that it should be in front of. The odd thing is, the fin would every once in a while be displayed correctly. The wings do similar stuff, sometimes in front of the body like it should be and other times behind the body when it should be in front. Sometimes it will be displayed wrng for a whole frame, other times it will flciker on the redraw. It all seems fairly random and I’m stumped. Thanks for any help you give and here’s what my render code looks like. Please note that this code is modified from the openGL superbible.

public void display(GLDrawable glDrawable) {
    GL gl=glDrawable.getGL();
    GLU glu=glDrawable.getGLU();
    int width=canvas.getWidth();
    int height=canvas.getHeight();


      gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);

    gl.glMatrixMode(GL.GL_PROJECTION);
    /**
     * Then we clear the projection matrix to the Identity matrix
     */
    gl.glLoadIdentity();
    glu.gluPerspective(90.0f,1.0f,0,-500);
    glu.gluLookAt(0.0f,100.0f,-50.0f,0.0f,0.0f,0.0f,0.0f,0.0f,1.0f);
    //gl.glOrtho(-width/2,width/2,-height/2,height/2,-500,500);
        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();
// Save the matrix state
      gl.glPushMatrix();
      //gl.glScalef(.5f,.5f,.5f);
      //gl.glTranslatef(-20.0f,-20.0f,0.0f);
        gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);


  // Nose Cone /////////////////////////////
  // Bright Green
        gl.glColor3ub((byte)0, (byte)255, (byte)0);
        gl.glBegin(gl.GL_TRIANGLES);
        gl.glVertex3f(0.0f, 0.0f, 60.0f);
        gl.glVertex3f(-15.0f, 0.0f, 30.0f);
        gl.glVertex3f(15.0f,0.0f,30.0f);

        gl.glVertex3f(15.0f,0.0f,30.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(0.0f, 0.0f, 60.0f);

        gl.glVertex3f(0.0f, 0.0f, 60.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(-15.0f,0.0f,30.0f);

        // Body of the Plane ////////////////////////
        // light gray

        gl.glColor3ub((byte)192,(byte)192,(byte)192);
        gl.glVertex3f(-15.0f,0.0f,30.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(0.0f, 0.0f, -56.0f);

        gl.glVertex3f(0.0f, 0.0f, -56.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(15.0f,0.0f,30.0f);

        gl.glVertex3f(15.0f,0.0f,30.0f);
        gl.glVertex3f(-15.0f, 0.0f, 30.0f);
        gl.glVertex3f(0.0f, 0.0f, -56.0f);


        ///////////////////////////////////////////////
        // Left wing
        // Dark gray
        gl.glColor3ub((byte)64,(byte)64,(byte)64);
        gl.glVertex3f(0.0f,2.0f,27.0f);
        gl.glVertex3f(-60.0f, 2.0f, -8.0f);
        gl.glVertex3f(60.0f, 2.0f, -8.0f);

        gl.glVertex3f(60.0f, 2.0f, -8.0f);
        gl.glVertex3f(0.0f, 7.0f, -8.0f);
        gl.glVertex3f(0.0f,2.0f,27.0f);

        gl.glVertex3f(60.0f, 2.0f, -8.0f);
        gl.glVertex3f(-60.0f, 2.0f, -8.0f);
        gl.glVertex3f(0.0f,7.0f,-8.0f);


        // Other wing top section
        gl.glVertex3f(0.0f,2.0f,27.0f);
        gl.glVertex3f(0.0f, 7.0f, -8.0f);
        gl.glVertex3f(-60.0f, 2.0f, -8.0f);

        // Tail section///////////////////////////////
        // Bottom of back fin
        gl.glColor3ub((byte)255,(byte)255,(byte)0);
        gl.glVertex3f(-30.0f, -0.50f, -57.0f);
        gl.glVertex3f(30.0f, -0.50f, -57.0f);
        gl.glVertex3f(0.0f,-0.50f,-40.0f);

        // top of left side
        gl.glVertex3f(0.0f,-0.5f,-40.0f);
        gl.glVertex3f(30.0f, -0.5f, -57.0f);
        gl.glVertex3f(0.0f, 4.0f, -57.0f);

        // top of right side
        gl.glVertex3f(0.0f, 4.0f, -57.0f);
        gl.glVertex3f(-30.0f, -0.5f, -57.0f);
        gl.glVertex3f(0.0f,-0.5f,-40.0f);

        // back of bottom of tail
        gl.glVertex3f(30.0f,-0.5f,-57.0f);
        gl.glVertex3f(-30.0f, -0.5f, -57.0f);
        gl.glVertex3f(0.0f, 4.0f, -57.0f);


        // Top of Tail section left
        gl.glColor3ub((byte)255,(byte)0,(byte)0);
        gl.glVertex3f(0.0f,0.5f,-40.0f);
        gl.glVertex3f(3.0f, 0.5f, -57.0f);
        gl.glVertex3f(0.0f, 25.0f, -65.0f);

        gl.glVertex3f(0.0f, 25.0f, -65.0f);
        gl.glVertex3f(-3.0f, 0.5f, -57.0f);
        gl.glVertex3f(0.0f,0.5f,-40.0f);


        // Back of horizontal section
        gl.glVertex3f(3.0f,0.5f,-57.0f);
        gl.glVertex3f(-3.0f, 0.5f, -57.0f);
        gl.glVertex3f(0.0f, 25.0f, -65.0f);
        gl.glEnd();

      gl.glPopMatrix();


}

What platform are you running on? If Windows, have you tried specifying -Dsun.java2d.noddraw=true on the command line? Does that affect the behavior?

Thank for the suggestion but it works the same with that command line parameter. I’m running windows XP and I have JOGL from November 19’th installed. I really looks like the depth testing is messed up because when I slowed it down and watched it frame by frame, it acts the same each time I run it. I’ll post the code I have for intializing opengl.

public void init(GLDrawable glDrawable) {
    GL gl=glDrawable.getGL();//Get the GL object from glDrawable
      float ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };

      gl.glEnable(gl.GL_DEPTH_TEST);      // Hidden surface removal
      gl.glEnable(gl.GL_CULL_FACE);            // Do not calculate inside of jet
      gl.glShadeModel (GL.GL_SMOOTH);
      gl.glFrontFace(gl.GL_CCW);            // Counter clock-wise polygons face out

// Lighting stuff
      gl.glEnable(gl.GL_LIGHTING);                  // Enable lighting

// Set light model to use ambient light specified by ambientLight
      gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT,ambientLight);

      gl.glEnable(gl.GL_COLOR_MATERIAL);      // Enable Material color tracking

// Front material ambient and diffuse colors track glColor
      gl.glColorMaterial(gl.GL_FRONT,gl.GL_AMBIENT_AND_DIFFUSE);

      gl.glClearColor(0.0f, 0.5f, 0.5f,1.0f);

}

Can you post complete source code for your example? The snippets of code you’ve posted look fine to me.

This is the whole JPanel that I put into a standard JFrame. The controler class comes next and the last is the Animated interface. These come mostly from the examples at http://www.stud.ntnu.no/~johanno/appletviewer.jsp?task=tutorials
I really only modified the render function, the initialization of opengl, and I changed it from an applet to an application.

/*******************************************/

import net.java.games.jogl.;
import javax.swing.
;

public class GLPanel3D extends JPanel implements GLEventListener, Animated{

private GLCanvas canvas;
  float xRot = 45.0f;
  float yRot = 45.0f;
/**
 * Constructor of the Panel.
 * The constructor creates a GLCanvas and then adds it to itself.
 */
public GLPanel3D() {
    super();

    /**
     * First we create the capabilities for our canvas
     */
    GLCapabilities capabilities=new GLCapabilities();
    capabilities.setHardwareAccelerated(true);      //We want hardware accelleration
    capabilities.setDoubleBuffered(true);           //And double buffering

    /**
     * Then we create the canvas.
     */
    canvas=GLDrawableFactory.getFactory().createGLCanvas(capabilities);

    /**
     * We add the eventlistener, so that the display will be updated at the appropriate times.
     */
    canvas.addGLEventListener(this);

    /**
     * Finally we add the canvas and set its size
     */
    this.add(canvas);
    this.setSize(500,500);
    canvas.setSize(500,500);//We want the JPanel and the GLCanvas to have the same size
    canvas.setVisible(true);//This is somehow necessary
}

/**
 * The init method will be called when the GLCanvas is constructed.
 * Here we put the basic settings that will only be called once.
 * @param glDrawable
 */
public void init(GLDrawable glDrawable) {
    GL gl=glDrawable.getGL();//Get the GL object from glDrawable
      float ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };

      gl.glEnable(gl.GL_DEPTH_TEST);      // Hidden surface removal
      gl.glEnable(gl.GL_CULL_FACE);            // Do not calculate inside of jet
      gl.glShadeModel (GL.GL_SMOOTH);
      gl.glFrontFace(gl.GL_CCW);            // Counter clock-wise polygons face out

// Lighting stuff
      gl.glEnable(gl.GL_LIGHTING);                  // Enable lighting

// Set light model to use ambient light specified by ambientLight
      gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT,ambientLight);

      gl.glEnable(gl.GL_COLOR_MATERIAL);      // Enable Material color tracking

// Front material ambient and diffuse colors track glColor
      gl.glColorMaterial(gl.GL_FRONT,gl.GL_AMBIENT_AND_DIFFUSE);

      gl.glClearColor(0.0f, 0.5f, 0.5f,1.0f);

/* gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(gl.GL_BLEND);
gl.glEnable(gl.GL_POINT_SMOOTH);
gl.glHint(gl.GL_POINT_SMOOTH_HINT,gl.GL_NICEST);
gl.glEnable(gl.GL_LINE_SMOOTH);
gl.glHint(gl.GL_LINE_SMOOTH_HINT,gl.GL_NICEST);
gl.glEnable(gl.GL_POLYGON_SMOOTH);
gl.glHint(gl.GL_POLYGON_SMOOTH_HINT,gl.GL_NICEST);*/
}

/**
 * This is the function where the drawing is done.
 * This method is called everytime repaint() is called.
 * JOGL uses Javas events, which makes it a lot easier to use.
 * @param glDrawable
 */
public void display(GLDrawable glDrawable) {
    GL gl=glDrawable.getGL();
    GLU glu=glDrawable.getGLU();

      gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);

    gl.glMatrixMode(GL.GL_PROJECTION);
    /**
     * Then we clear the projection matrix to the Identity matrix
     */
    gl.glLoadIdentity();
    glu.gluPerspective(90.0f,1.0f,0,-500);
    glu.gluLookAt(0.0f,100.0f,-50.0f,0.0f,0.0f,0.0f,0.0f,0.0f,1.0f);
    //gl.glOrtho(-width/2,width/2,-height/2,height/2,-500,500);
        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();
// Save the matrix state
      gl.glPushMatrix();
      //gl.glScalef(.5f,.5f,.5f);
      //gl.glTranslatef(-20.0f,-20.0f,0.0f);
        gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);


  // Nose Cone /////////////////////////////
  // Bright Green
        gl.glColor3ub((byte)0, (byte)255, (byte)0);
        gl.glBegin(gl.GL_TRIANGLES);
        gl.glVertex3f(0.0f, 0.0f, 60.0f);
        gl.glVertex3f(-15.0f, 0.0f, 30.0f);
        gl.glVertex3f(15.0f,0.0f,30.0f);

        gl.glVertex3f(15.0f,0.0f,30.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(0.0f, 0.0f, 60.0f);

        gl.glVertex3f(0.0f, 0.0f, 60.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(-15.0f,0.0f,30.0f);

        // Body of the Plane ////////////////////////
        // light gray

        gl.glColor3ub((byte)192,(byte)192,(byte)192);
        gl.glVertex3f(-15.0f,0.0f,30.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(0.0f, 0.0f, -56.0f);

        gl.glVertex3f(0.0f, 0.0f, -56.0f);
        gl.glVertex3f(0.0f, 15.0f, 30.0f);
        gl.glVertex3f(15.0f,0.0f,30.0f);

        gl.glVertex3f(15.0f,0.0f,30.0f);
        gl.glVertex3f(-15.0f, 0.0f, 30.0f);
        gl.glVertex3f(0.0f, 0.0f, -56.0f);


        ///////////////////////////////////////////////
        // Left wing
        // Dark gray
        gl.glColor3ub((byte)64,(byte)64,(byte)64);
        gl.glVertex3f(0.0f,2.0f,27.0f);
        gl.glVertex3f(-60.0f, 2.0f, -8.0f);
        gl.glVertex3f(60.0f, 2.0f, -8.0f);

        gl.glVertex3f(60.0f, 2.0f, -8.0f);
        gl.glVertex3f(0.0f, 7.0f, -8.0f);
        gl.glVertex3f(0.0f,2.0f,27.0f);

        gl.glVertex3f(60.0f, 2.0f, -8.0f);
        gl.glVertex3f(-60.0f, 2.0f, -8.0f);
        gl.glVertex3f(0.0f,7.0f,-8.0f);


        // Other wing top section
        gl.glVertex3f(0.0f,2.0f,27.0f);
        gl.glVertex3f(0.0f, 7.0f, -8.0f);
        gl.glVertex3f(-60.0f, 2.0f, -8.0f);

        // Tail section///////////////////////////////
        // Bottom of back fin
        gl.glColor3ub((byte)255,(byte)255,(byte)0);
        gl.glVertex3f(-30.0f, -0.50f, -57.0f);
        gl.glVertex3f(30.0f, -0.50f, -57.0f);
        gl.glVertex3f(0.0f,-0.50f,-40.0f);

        // top of left side
        gl.glVertex3f(0.0f,-0.5f,-40.0f);
        gl.glVertex3f(30.0f, -0.5f, -57.0f);
        gl.glVertex3f(0.0f, 4.0f, -57.0f);

        // top of right side
        gl.glVertex3f(0.0f, 4.0f, -57.0f);
        gl.glVertex3f(-30.0f, -0.5f, -57.0f);
        gl.glVertex3f(0.0f,-0.5f,-40.0f);

        // back of bottom of tail
        gl.glVertex3f(30.0f,-0.5f,-57.0f);
        gl.glVertex3f(-30.0f, -0.5f, -57.0f);
        gl.glVertex3f(0.0f, 4.0f, -57.0f);


        // Top of Tail section left
        gl.glColor3ub((byte)255,(byte)0,(byte)0);
        gl.glVertex3f(0.0f,0.5f,-40.0f);
        gl.glVertex3f(3.0f, 0.5f, -57.0f);
        gl.glVertex3f(0.0f, 25.0f, -65.0f);

        gl.glVertex3f(0.0f, 25.0f, -65.0f);
        gl.glVertex3f(-3.0f, 0.5f, -57.0f);
        gl.glVertex3f(0.0f,0.5f,-40.0f);


        // Back of horizontal section
        gl.glVertex3f(3.0f,0.5f,-57.0f);
        gl.glVertex3f(-3.0f, 0.5f, -57.0f);
        gl.glVertex3f(0.0f, 25.0f, -65.0f);
        gl.glEnd();

      gl.glPopMatrix();


}
/**
 * Reshape will be called everytime the canvas changes shape.
 * This is a good place the MATRIX setup if you want the 'camera' settings to change when the display is resized.
 * @param glDrawable
 * @param i
 * @param i1
 * @param i2
 * @param i3
 */
public void reshape(GLDrawable glDrawable, int i, int i1, int i2, int i3) {



}

public void displayChanged(GLDrawable glDrawable, boolean b, boolean b1) {
}

public void timeStep(long time) {
    yRot+=2;
    canvas.repaint();
}

}

Here’s the rest of the code. That wouldn’t fit in the last post.

/******************************************/

import java.awt.;
import java.awt.event.
;
import javax.swing.;
import java.awt.
;

public class JOGLApp extends JFrame implements Runnable, ActionListener {

boolean running;
Animated a;
Animated b;
Thread animThread;
JButton QuitButton;

public static void main(String[] args)
{
        JOGLApp myJ = new JOGLApp();
        myJ.start();
        myJ.run();

  }

  public void actionPerformed(ActionEvent ae)
  {
        Object source = ae.getSource();
        if(source == QuitButton){
              running = false;
        }
  }

  public JOGLApp()
  {
        this.setTitle("Jogl app");


        this.setSize(800,600);
        this.init();
        this.setVisible(true);
  }

public void init() {
    this.getContentPane().setLayout(new BorderLayout());
    boolean hardware = false;

    QuitButton = new JButton("Quit");
        QuitButton.addActionListener(this);
    JPanel pane = new JPanel();
        pane.add(QuitButton);
        this.getContentPane().add(pane,BorderLayout.SOUTH);

    try {
        Class.forName("net.java.games.jogl.GLCanvas");

        hardware = true;

    } catch (ClassNotFoundException e) {

        hardware = false;
    }

    if (hardware) {
        try {

            Class c2 = Class.forName("GLPanel3D");
            JPanel hardw2 = (JPanel) c2.newInstance();
            this.getContentPane().add(hardw2,BorderLayout.CENTER);
            b=(Animated)hardw2;



        } catch (Exception e) {
            hardware=false;

        }
    } if (!hardware) {
        this.getContentPane().add(new JLabel("JOGL not installed"),BorderLayout.CENTER);
    }

}
public void start()
{

    if(animThread==null)
    {
        animThread=new Thread(this);
        animThread.start();
    }
}
public void run()
{

    running=true;
    while(running)
    {
              try {

              b.timeStep(10);
            Thread.sleep(800);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    System.exit(0);

}
public void stop()
{
    running=false;
    if (animThread != null)
    {
          animThread = null;
    }

}

}

/****************************************/

/**

  • Created by IntelliJ IDEA.
  • Date: May 24, 2004
  • Time: 2:44:43 PM
  • To change this template use Options | File Templates.
    */
    public interface Animated {
    public void timeStep(long time);
    }

There are two problems. The first is definitely that you are calling JOGLApp.run() from two different threads: the animThread and the main thread. The call to myJ.run() should be removed from main(). I don’t really understand why that should cause flickering because there should be enough synchronization in JOGL’s internals to prevent it, so if you want to file a low-priority bug on that with the JOGL Issue Tracker feel free. The second I haven’t gotten to the bottom of, but I suspect it’s due to the fact that you aren’t specifying vertex normals with glNormal3f, so the default normal (probably 0,0,0) is being specified for all vertices. At least a couple of your vertices aren’t exactly correct, as well; compare the top of tail section left and right. Hope this helps.

The first problem mentioned above seems to be addressed by putting a gl.glFinish() or gl.glFlush() at the end of your display() routine, so this appears to be an application / multithreading bug and not a bug in JOGL itself. I still don’t know the cause of the flickering polygons within the shape, though.

Quick thought just by skimming thru the code:
you’re adding a heavy-weight GLCanvas to
a light-weight JPanel, which is not recommended.
You will have flickers (not related to the one
you described) when you resize or repaint the
JPanel.

Wow, it’s awsome when tutorials give you bad advice. That light-wieght/heavy-weight issue was part of the code copied and pasted from the tutorial I mentioned earlier. So anyway, how should I change it? I currently add GLCanvas -> JPanel -> JFrame. Should I just make the GLPanel extend the GLCanvas class and just add it to the JFrame (GLCanvas -> JFrame)? Or should I use some other class instead of the GLCanvas (?class -> JPanel -> JFrame)? Or do I have to something completely different? And by the way, do you guys think that I should go through and specify all the vertex normals? Anyway, thanks for all your help and for not flaming my ignorance.

I don’t think the presence of the JPanel is causing your flicker. The first thing I tried was restructuring your application to add just the GLCanvas to a parent Frame and there was no change in behavior.

Does that mean that there’s no problem with mixing light-weight and heavy-weight components or is there a problem with that mixing but that my problem was something else?

There can be problems mixing lightweight and heavyweight components. This article describes some of the high-level issues:

http://java.sun.com/products/jfc/tsc/articles/mixing/

JOGL seems to have more difficulties than just these in some situations. Some of these issues are due to Java2D’s use of DirectDraw on Windows and can be worked around by specifying -Dsun.java2d.noddraw=true. Others haven’t been fully debugged yet and tend to come out only in more complex applications. Tabbed panes and split panes seem to be problematic.

However, none of these issues are the root cause of the flicker in your application.

Well, I think I found the problem, I think I messed up the perspective view code. When I switched the view back to ortho it was perfectly smooth. I’m not sure how to make the perspective work without the flicker, but I’m almost positive that’s the problem.