JOGL not rendering any frames but the first

I am new to OpenGL and 3d programmin in general. I am working on a simple program to try things out in.

I can draw in the scene, but when I added an Animator to the canvas, the canvas turns out blank. I added some code to output the canvas to a file and have discovered that the first frame displays correctly, but all frames after that fail to draw anything.

Another problem is that I have three triangles here, two of them a behind the other one… but draw on top of the closer one… creating a weird optical illusion.

Below is the code for my jogl panel, does anyone see a problem or have any ideas?

Thanks


package ljb.first3d;
import net.java.games.jogl.*;
import net.java.games.jogl.util.*;
import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import java.nio.*;
import java.awt.*;
import java.awt.image.*;

public class ThreeDPanel extends JPanel implements GLEventListener
{
  private GLCanvas canvas;

  public ThreeDPanel()
  {
    super();

    GLCapabilities capabilities=new GLCapabilities();
    capabilities.setHardwareAccelerated(true);      //We want hardware acceleration
    capabilities.setDoubleBuffered(true);           //And double buffering

    canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
    canvas.addGLEventListener(this);
    this.add(canvas);
    Animator animator;
    animator = new Animator(canvas);
    animator.start();

    this.add(canvas);
    int w = 800, h = 600;
    this.setSize(w,h);

    canvas.setSize(w,h);//We want the JPanel and the GLCanvas to have the same size

    canvas.setVisible(true);//This is somehow necessary
    // begin render loop
    new CameraLooper().start();
  }

  public void init(GLDrawable glDrawable)
  {
    GL myGL=glDrawable.getGL();//Get the GL object from glDrawable
    myGL.glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
    myGL.glShadeModel (GL.GL_FASTEST);
  }

  public void reshape(GLDrawable glDrawable, int i, int i1, int i2, int i3)
  {
    GL myGL=glDrawable.getGL();
    int width=canvas.getWidth();
    int height=canvas.getHeight();
  }

  public void display(GLDrawable glDrawable)
  {
    GL gl=glDrawable.getGL();
    GLU glu = glDrawable.getGLU();

    gl.glMatrixMode(GL.GL_PROJECTION);
    glu.gluPerspective(45.0, 900 / 600, 0.1, 100.0);

    gl.glMatrixMode(GL.GL_MODELVIEW);

    gl.glLoadIdentity();
    glu.gluLookAt(camx, camy, camz, 0, 0, 0, 0, 1, 0);

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

    drawHorizPlane(gl,10,10);

    drawTriangle(gl,0,0,0,1,1);

    gl.glPushMatrix();

    gl.glTranslatef(1, 0, -1);

    drawTriangle(gl,0,0,0,1,1);

    gl.glPopMatrix();

    gl.glPushMatrix();

    gl.glTranslatef(-1, 0, -1);

    drawTriangle(gl,0,0,0,1,1);

    gl.glPopMatrix();

    //gl.glEnd();
    writeBufferToFile(glDrawable, new File("c:\\opengl"+(num++)+".png"));
  }

  private int num = 0;

  private void drawTriangle(GL gl, int x, int y, int z, int width, int height)
  {

    gl.glBegin(GL.GL_TRIANGLES);

    byte r,g,b;

    r = (byte)255;
    g = (byte)0;
    b = (byte)0;

    gl.glColor3ub(r,g,b);
    gl.glVertex3i(x,y + height,z);

    r = (byte)0;
    g = (byte)255;
    b = (byte)0;

    gl.glColor3ub(r,g,b);
    gl.glVertex3i(x + width, y - height, z);

    r = (byte)0;
    g = (byte)0;
    b = (byte)255;

    gl.glColor3ub(r,g,b);
    gl.glVertex3i(x - width, y - height, z);

    gl.glEnd();
  }

  private void drawHorizPlane(GL gl, int width, int height)
  {
    gl.glBegin(GL.GL_TRIANGLES);
    byte r,g,b;

    r = (byte)0;
    g = (byte)150;
    b = (byte)0;

    gl.glColor3ub(r,g,b);

    gl.glVertex3i(-width,0,-height);
    gl.glVertex3i(width, 0, -height);
    gl.glVertex3i(-width, 0, height);

    r = (byte)0;
    g = (byte)0;
    b = (byte)150;

    gl.glColor3ub(r,g,b);

    gl.glVertex3i(-width, 0, height);
    gl.glVertex3i(width, 0, -height);
    gl.glVertex3i(width, 0, height);

    gl.glEnd();
  }

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

  private double camx = 0;
  private double camy = 0;
  private double camz = 6;

  private class CameraLooper extends Thread
  {
    public void run()
    {
      boolean fx = true, fy = true, fz = true;
      while(true)
      {
        if(camx >= 100 || camx <= -100)
          fx = !fx;
        if(camy >= 100 || camy <= -100)
          fy = !fy;
        if(camz >= 100 || camz <= -100)
          fx = !fx;
        if(fx)
          camx += .01;
        else
          camx -= .01;
        if(fy)
          camy += .01;
        else
          camy -= .01;
        if(fz)
          camz += .01;
        else
          camz -= .01;
        //repaint();
        try
        {
          Thread.sleep(1);
        }
        catch(Exception e)
        {
          e.printStackTrace();
        }
        //System.out.println("new frame");
      }
    }
  }

  private void writeBufferToFile(GLDrawable drawable, File outputFile)
  {
     int width = drawable.getSize().width;
     int height = drawable.getSize().height;

     ByteBuffer pixelsRGB = BufferUtils.newByteBuffer(width * height * 3);

     GL gl = drawable.getGL();

     gl.glReadBuffer(GL.GL_BACK);
     gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);

     gl.glReadPixels(0,     // GLint x
       0,     // GLint y
       width,      // GLsizei width
       height,    // GLsizei height
       GL.GL_RGB,    // GLenum format
       GL.GL_UNSIGNED_BYTE,   // GLenum type
       pixelsRGB);     // GLvoid *pixels

   int[] pixelInts = new int[width * height];

   // Convert RGB bytes to ARGB ints with no transparency. Flip image vertically by reading the
   // rows of pixels in the byte buffer in reverse - (0,0) is at bottom left in OpenGL.

   int p = width * height * 3; // Points to first byte (red) in each row.
   int q;   // Index into ByteBuffer
   int i = 0;   // Index into target int[]
   int w3 = width*3;    // Number of bytes in each row

   for (int row = 0; row < height; row++) {
    p -= w3;
    q = p;
    for (int col = 0; col < width; col++) {
     int iR = pixelsRGB.get(q++);
     int iG = pixelsRGB.get(q++);
     int iB = pixelsRGB.get(q++);

     pixelInts[i++] = 0xFF000000
       | ((iR & 0x000000FF) << 16)
       | ((iG & 0x000000FF) << 8)
       | (iB & 0x000000FF);
    }

   }

   BufferedImage bufferedImage =
    new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

   bufferedImage.setRGB(0, 0, width, height, pixelInts, 0, width);

   try {
    ImageIO.write(bufferedImage, "PNG", outputFile);
   } catch (IOException e) {
    e.printStackTrace();
   }

  }
}

I can draw in the scene, but when I added an Animator to the canvas, the > canvas turns out blank.

You did not reset the projection matrix before loading the new camera position. The changes for every frame get multiplied and objects quickly move out of the visible area unless the matrix is reset each time.

public void display(GLDrawable glDrawable)
{
GL gl=glDrawable.getGL();
GLU glu = glDrawable.getGLU();

gl.glMatrixMode(GL.GL_PROJECTION); 
gl.glLoadIdentity();                                           /// <<<< HERE >>>> 
glu.gluPerspective(45.0, 900 / 600, 0.1, 100.0); 

Another problem is that I have three triangles here, two of them a behind > the other one… but draw on top of the closer one… creating a weird
optical illusion.

You either need to enable the depth buffer in glInit or draw all triangles back to front in glDisplay.

Thanks for the help. That fixed part of the problem. Now at least I can get 21 frames before the triangles move out of the range of the camera. Something must be wrong with the matrix math. At least now I know where to start looking.
Anybody want to point me at setting up the depth buffer? That would be easier than drawing them in order. Esp. after I start rendering more complex scenes.