Basic Hello World app not rendering

As a continuation from my previous thread, i managed to get the time to have another look over it. So I started trimming it down to a bare minimum, and i’ve got to the point where it looks nigh on identical to the Gear demo, yet it still doesn’t render ???

If i add a mismatched .glBegin() at the bottom of the draw() method, it will render. Also, if i do this to make it render the lines, then they will shift and duplicate if the window is dragged around :frowning: Anyone see my (probably basic) mistake?


package testPackage;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import net.java.games.jogl.*;

/**
 *   Vectrix
 * 
 * @author John
 */
public class Vectrix implements GLEventListener
{
      public static final Vectrix app = new Vectrix();
      
      private Frame frame;
      
//      private MouseHandler mouseHandler;
      private Animator animator;
      

      private GLCanvas canvas;

      /**
       * 
       */
      private Vectrix()
      {
            System.out.println("Vectrix instance created");
            
            // Canvas setup
            GLCapabilities caps = new GLCapabilities();
            caps.setDoubleBuffered(true);
            caps.setAlphaBits(8);
            caps.setStencilBits(8);
            
            canvas = GLDrawableFactory.getFactory().createGLCanvas(caps);
            canvas.addGLEventListener(this);
            
            // Frame setup
            frame = new Frame("Vectrix");
            frame.add(canvas);
            frame.setSize(800, 600);

            frame.addWindowListener(      new WindowAdapter()
                                                      {
                                                            public void windowClosing(WindowEvent e)
                                                            {
                                                                  animator.stop();
                                                                  System.exit(0);
                                                            }
                                                      }
                                                );
            
            // Event handlers
            animator = new Animator(canvas);
      //      mouseHandler = new MouseHandler();
            
      //      frame.addMouseListener(mouseHandler);
      }
      
      public void initialiseDisplay()
      {
            frame.show();
      }
      
      public void run()
      {
            animator.start();
      }

      public static void main(String[] args)
      {
            System.out.println("Vectrix starting...");
            
            app.initialiseDisplay();
      
            // Other loading/initialisation
            // ..
            
            // Start main game loop
            app.run();
      }

      
      // GL Event Listener methods
      
      // Called when GL has been initialised for the first time.
      public void init(GLDrawable canvas)
      {
            System.out.println("Vectrix.init(): GL init event");
            
            GL gl = canvas.getGL();
            
            gl.glMatrixMode(GL.GL_PROJECTION_MATRIX);
                  gl.glLoadIdentity();
            gl.glMatrixMode(GL.GL_TEXTURE);
                  gl.glLoadIdentity();
            gl.glMatrixMode(GL.GL_MODELVIEW);
                  gl.glLoadIdentity();
                  
      //      gl.glFrontFace(GL.GL_CCW);
      //      gl.glEnable(GL.GL_CULL_FACE);
      //      gl.glEnable(GL.GL_DEPTH_TEST);
      }

      public void display(GLDrawable canvas)
      {
            GL      gl      = canvas.getGL();
            GLU      glu      = canvas.getGLU();
            
            gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);
            
            //                  l/r            t/b            near/far
            gl.glOrtho(0, 4,      0, 3,      -8, 8);
            
            // animate..
            gl.glPushMatrix();
            {
                  gl.glBegin(GL.GL_LINES);
                  {
                        int xMin = 0;
                        int xMax = 10;
                        gl.glColor3f(1f, 0f, 0f);
                        
                        for (int x=xMin; x<=xMax; x++)
                        {
                              gl.glVertex3f(x, -1, 0f);
                              gl.glVertex3f(x, +1, 0f);
      
                        }
                        
                        gl.glVertex3f(0f, 0f, 0f);
                        gl.glVertex3f(4f, 4f, 4f);
                        
                  }
                  gl.glEnd();
            }
            gl.glPopMatrix();
            
            gl.glBegin(GL.GL_LINES);// Mismatched begin causes drawing to work!
      //      gl.glEnd();
      }


      public void reshape(GLDrawable arg0, int arg1, int arg2, int arg3, int arg4)
      {

      }

      public void displayChanged(GLDrawable arg0, boolean arg1, boolean arg2)
      {

      }
}

Thanks

There’s been a few posts about glBegin/glEnd oddness - I don’t suppose JOGL is calling glEnd after returning from your display method, is it?

Seeing as there’s been a few mentions of it, someone should probably have a look now…

Hmm - I added in the DebugGL and stepped though the Animator and found a couple of things:

  • The animator is working correctly, calling display in a loop - yet for some reason this doesn’t trigger a FPS counter in Fraps. Probably due to there being an error in the drawing code.

  • I had an error in some setup code (GL.GL_PROJECTION_MATRIX instead of GL.GL_PROJECTION) but thats irrelevant, since all i was doing was a setIdentity().

  • My glEnd causes an error - more specifically a INVALID_OPERATION. This is caused by “A function other than glVertex, glColor […] was called, or called without a corresponding call to glBegin”
    I have stripped the code down to a bare minimum (begin, two vertex calls, end) and still get the error. And it throws an exception on my glEnd, so it can’t be due to something that is done after display() returns…

Put simply, something fishy is afoot, and i think theres some odd undocumented behaviour, or somethings horibly broken >:(

Edit: More weirdness, calling glBegin() twice in a row doesn’t cause an error, despite it being clearly stated in the GL spec that it should. :o

Edit again: I found out why i get funny bluring when dragging the window - it seems like glClear isn’t doing its job properly - looks like the viewport gets out of sync with the canvas, as sometimes it affects all of the canvas, sometimes none, sometimes just the bottom half.

There are two problems here. First is a problem in your code, second is a problem with JOGL.

  1. You are forgetting to switch the matrix mode to GL_PROJECTION before calling glOrtho(); as such you are affecting the model and not the camera. Also, though your code was correct, you comment for glOrtho() was wrong – it’s b/t not t/b

  2. The reason you’re not seeing your drawing is because you’re not setting the camera inside resize(). Under the hood, JOGL calls glViewport() whenever the underlying canvas changes size (including when the frame is first shown), and then calls GLDrawable.reshape(). At this point in time the canvas extents have been sent to GL and your camera calls work fine.

However, I’m not sure why your app does not work when calling glOrtho() outside of reshaoe() – AFAICT it should still work correctly modulo a one-frame error after a reshape.

This problem is reproducible. If you look at the code below, when setCameraInReshape = true the app renders fine; when set to false the app does not render.

I will file an issue on the project page.

-chris


 
import java.awt.Frame; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
 
import net.java.games.jogl.*; 
 
/** 
 *   Vectrix 
 *  
 * @author John 
 * @author Ckline modified to demostrate bug
 */ 
public class Vectrix implements GLEventListener 
{
  // BUG REPRO: app does not render correctly when setCameraInReshape is false
  private boolean setCameraInReshape = true;

  public static Vectrix app = new Vectrix(); 
  
  private Frame frame; 
  
  // private MouseHandler mouseHandler; 
  private Animator animator; 
  
 
  private GLCanvas canvas; 
 
  /** 
   *  
   */ 
  private Vectrix() 
  { 
    System.out.println("Vectrix instance created"); 
    
    // Canvas setup 
    GLCapabilities caps = new GLCapabilities(); 
    caps.setDoubleBuffered(true); 
    caps.setAlphaBits(8); 
    caps.setStencilBits(8); 
    canvas = GLDrawableFactory.getFactory().createGLCanvas(caps); 
     
    //canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); 
    canvas.addGLEventListener(this); 
    canvas.setGL(new DebugGL(canvas.getGL()));
    // Frame setup 
    frame = new Frame("Vectrix"); 
    frame.add(canvas); 
    frame.setSize(800, 600); 
 
    frame.addWindowListener(
      new WindowAdapter() 
      { 
        public void windowClosing(WindowEvent e) 
        { 
          animator.stop(); 
          System.exit(0); 
        } 
      } 
      ); 
   
    // Event handlers 
    animator = new Animator(canvas); 
  } 
  
  public void initialiseDisplay() 
  { 
    frame.show(); 
  } 
  
  public void run() 
  { 
    animator.start(); 
  } 
 
  public static void main(String[] args) 
  { 
    System.out.println("Vectrix starting..."); 
   
    app = new Vectrix(); 
    app.initialiseDisplay(); 
  
    // Other loading/initialisation 
    // .. 
   
    // Start main game loop 
    app.run(); 
  } 
 
  
  // GL Event Listener methods 
  
  // Called when GL has been initialised for the first time. 
  public void init(GLDrawable canvas) 
  { 
    System.out.println("Vectrix.init(): GL init event"); 
   
    GL gl = canvas.getGL(); 
   
    gl.glMatrixMode(GL.GL_PROJECTION); 
    gl.glLoadIdentity(); 
    gl.glMatrixMode(GL.GL_TEXTURE); 
    gl.glLoadIdentity(); 
    gl.glMatrixMode(GL.GL_MODELVIEW); 
    gl.glLoadIdentity(); 
    
  } 
 
  public void display(GLDrawable canvas) 
  {
    //System.err.println("DISPLAY THREAD: " + Thread.currentThread());
    GL gl = canvas.getGL(); 
    GLU glu = canvas.getGLU(); 
   
    gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f); 
    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); 
  
    if (!setCameraInReshape)
    {
      //   l/r  b/t  near/far 
      gl.glMatrixMode(GL.GL_PROJECTION); 
      gl.glOrtho(0, 4, 0, 3, -8, 8); 
      gl.glMatrixMode(GL.GL_MODELVIEW); 
    }
  
    gl.glPushMatrix(); 
    {
      // draw a polygon 
      gl.glBegin(GL.GL_POLYGON); 
      gl.glColor3f(1f, 0f, 0f); 
      gl.glVertex3f(.25f, .25f, 0f); 
      gl.glVertex3f(.75f, .25f, 0f); 
      gl.glVertex3f(.75f, .75f, 0f); 
      gl.glVertex3f(.25f, .75f, 0f); 
      gl.glEnd();   

      // draw some lines
      gl.glBegin(GL.GL_LINES); 
      { 
        int xMin = 0; 
        int xMax = 10; 
        gl.glColor3f(1f, 0f, 0f); 
     
        for (int x=xMin; x<=xMax; x++) 
        { 
          gl.glVertex3f(x, -1, 0f); 
          gl.glVertex3f(x, +1, 0f); 
  
        } 
     
        gl.glVertex3f(0f, 0f, 0f); 
        gl.glVertex3f(4f, 4f, 4f); 
     
      } 
      gl.glEnd();
      
    } 
    gl.glPopMatrix(); 
   
  } 
 
 
  public void reshape(GLDrawable arg0, int arg1, int arg2, int arg3, int arg4) 
  {
    //System.err.println("RESHAPE THREAD: " + Thread.currentThread());
    GL gl = arg0.getGL();

    System.out.println("Vectrix.init(): GL reshape event " + arg1 + " " + arg2
                       + " " + arg3 + " " + arg4); 

    if (setCameraInReshape)
    {
      //   l/r  b/t  near/far 
      gl.glMatrixMode(GL.GL_PROJECTION); 
      gl.glOrtho(0, 4, 0, 3, -8, 8); 
    }

  } 
 
  public void displayChanged(GLDrawable arg0, boolean arg1, boolean arg2) 
  { 
 
  } 
} 

Just to follow up, I’ve posted a bug about this at

http://jogl.dev.java.net/issues/show_bug.cgi?id=14

I believe it is a threading issue that arises because the AWT canvas is reshaped in a different thread than the one that calls GLDrawable.reshape(). However, I defer to those who understand the AWT integration better than I do.

-chris

Thanks for the help, this is really getting on my nerves now. A few more questions though:

  1. I modified my own code, and even tried a straight copy-paste from your modified version, yet i still get exceptions thrown from DebugGL. I’m going to assume that debug gl is broken for the time being until i hear otherwise. Edit: The Gears demo suffers from exactly the same problem if a simple glbegin/end is included.

  2. I had indeed forgotten to switch matrix modes :-[ But i have no idea how this could be the result, or even how this could be a threading problem - glOrtho is just a wrapper around a matrix op, why will this single operation fail, yet i can happily use glTranslatef and glRotatef?

Again, I appreciate you filing the bug report, hopefully this will be sorted pretty quickly.

Using an improper matrix mode will not trigger a GL error, you’ll just get incorrect rendering results because you’re modifying the modelview matrix (used to transform the vertices, etc) rather than the projection matrix (used to project world space vertices into camera space). I was just pointing it out because if you try to do anything more complicated with the camera in the future you would get incorrect rendering, and it would be a subtle bug to track down.

I have no idea why you’re getting errors from the DebugGL when using the code I sent you. It runs fine on my machine (GeforceFX 5800, drivers 41.10) with DebugGL enabled. AFAIK DebugGL works fine. Could you paste a stack trace?

If you’re getting errors with the unmodified Gears demo, something weird is definitely going on. What hardware and driver version are you using, and with what JVM version?

-chris

[quote]Using an improper matrix mode will not trigger a GL error, you’ll just get incorrect rendering results…
[/quote]
That was my point :slight_smile: Its just another matrix manipulation - having glOrtho fail, yet glTranslatef and glRotatef work normally makes no sense.

[quote]I have no idea why you’re getting errors from the DebugGL when using the code I sent you. It runs fine on my machine (GeforceFX 5800, drivers 41.10) with DebugGL enabled. AFAIK DebugGL works fine. Could you paste a stack trace?
[/quote]
Sure:

Vectrix instance created
Vectrix starting...
Vectrix instance created
Vectrix.init(): GL init event
Vectrix.init(): GL reshape event 0 0 792 566
net.java.games.jogl.GLException: glGetError() returned the following error codes after a call to glEnd(): GL_INVALID_OPERATION 
      at net.java.games.jogl.DebugGL.checkGLGetError(DebugGL.java:9914)
      at net.java.games.jogl.DebugGL.glEnd(DebugGL.java:2199)
      at testPackage.JoglTest.display(JoglTest.java:139)
      at net.java.games.jogl.impl.GLDrawableHelper.display(GLDrawableHelper.java:77)
      at net.java.games.jogl.GLCanvas$DisplayAction.run(GLCanvas.java:173)
      at net.java.games.jogl.impl.GLContext.invokeGL(GLContext.java:183)
      at net.java.games.jogl.GLCanvas.display(GLCanvas.java:75)
      at testPackage.Animator$1.run(Animator.java:102)
      at java.lang.Thread.run(Thread.java:536)


I would hope this isn’t a driver problem, since eveything else works :stuck_out_tongue: System is a GeForce2 GTS, drivers were the latest a few weeks ago, something like 44.03 winXP ones. JRE is 1.4.0

[quote]If you’re getting errors with the unmodified Gears demo, something weird is definitely going on.
[/quote]
Only subtly altered - it works fine as-is, but just a simple begin, 2 vertex3f’s and an end causes the same results. I was just using it since the gears is a set of base code that is known to work.

Well, actually, it does make a little sense. glOrtho() is meant to be a projection matrix operation, and as such I believe it assumes that glViewport() has been called correctly already (something that is done under the hood in GLCanvas.reshape()). glTranslatef() makes no such assumptions since it operates on any matrix.

My guess is, like I said in an earlier post, is that the current implementation assumes that camera operations will be done in GLDrawable.reshape(), after the underlying canvas has called glViewport(). I believe this assumption is not realistic, and hence I filed the bug.

Regarding your stack trace, it’s hard for me to diagnose since your line numbers do not match mine (and neither does the name of the class). If you posted the exact source file it would be easier to diagnose. Also, please post your modified Gears demo in entirety; I will need to see the modifications you made before coming to any conclusions.

-chris

[quote]If you posted the exact source file it would be easier to diagnose. Also, please post your modified Gears demo in entirety; I will need to see the modifications you made before coming to any conclusions.
[/quote]
No problem - semantically nothings changed, but I auto formated it, so thats the cause of the line numbers being different.

package testPackage;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import net.java.games.jogl.*;

/**  
 *   Vectrix  
 *   
 * @author John  
 * @author Ckline modified to demostrate bug 
 */
public class JoglTest implements GLEventListener
{
      // BUG REPRO: app does not render correctly when setCameraInReshape is false 
      private boolean setCameraInReshape = true;

      public static JoglTest app = new JoglTest();

      private Frame frame;

      // private MouseHandler mouseHandler;  
      private Animator animator;

      private GLCanvas canvas;

      /**  
       *   
       */
      private JoglTest()
      {
            System.out.println("Vectrix instance created");

            // Canvas setup  
            GLCapabilities caps = new GLCapabilities();
            caps.setDoubleBuffered(true);
            caps.setAlphaBits(8);
            caps.setStencilBits(8);
            canvas = GLDrawableFactory.getFactory().createGLCanvas(caps);

            //canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());  
            canvas.addGLEventListener(this);
            canvas.setGL(new DebugGL(canvas.getGL()));
            
            // Frame setup  
            frame = new Frame("Vectrix");
            frame.add(canvas);
            frame.setSize(800, 600);

            frame.addWindowListener(new WindowAdapter()
            {
                  public void windowClosing(WindowEvent e)
                  {
                        animator.stop();
                        System.exit(0);
                  }
            });

            // Event handlers  
            animator = new Animator(canvas);
      }

      public void initialiseDisplay()
      {
            frame.show();
      }

      public void run()
      {
            animator.start();
      }

      public static void main(String[] args)
      {
            System.out.println("Vectrix starting...");

            app = new JoglTest();
            app.initialiseDisplay();

            // Other loading/initialisation  
            // ..  

            // Start main game loop  
            app.run();
      }

      // GL Event Listener methods  

      // Called when GL has been initialised for the first time.  
      public void init(GLDrawable canvas)
      {
            System.out.println("Vectrix.init(): GL init event");

            GL gl = canvas.getGL();

            gl.glMatrixMode(GL.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glMatrixMode(GL.GL_TEXTURE);
            gl.glLoadIdentity();
            gl.glMatrixMode(GL.GL_MODELVIEW);
            gl.glLoadIdentity();

      }

      public void display(GLDrawable canvas)
      {
            //System.err.println("DISPLAY THREAD: " + Thread.currentThread()); 
            GL gl = canvas.getGL();
            GLU glu = canvas.getGLU();

            gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
            gl.glClear(
                  GL.GL_COLOR_BUFFER_BIT
                        | GL.GL_DEPTH_BUFFER_BIT
                        | GL.GL_STENCIL_BUFFER_BIT);

            if (!setCameraInReshape)
            {
                  //   l/r  b/t  near/far  
                  gl.glMatrixMode(GL.GL_PROJECTION);
                  gl.glOrtho(0, 4, 0, 3, -8, 8);
                  gl.glMatrixMode(GL.GL_MODELVIEW);
            }

            gl.glPushMatrix();
            {
                  gl.glTranslatef(0.5f, 0f, 0f);
                  gl.glRotatef(45f, 0f, 0f, 1f);
                  
                  // draw a polygon
                  gl.glBegin(GL.GL_POLYGON);
                  gl.glColor3f(1f, 0f, 0f);
                  gl.glVertex3f(.25f, .25f, 0f);
                  gl.glVertex3f(.75f, .25f, 0f);
                  gl.glVertex3f(.75f, .75f, 0f);
                  gl.glVertex3f(.25f, .75f, 0f);
                  gl.glEnd();

                  // draw some lines 
                  gl.glBegin(GL.GL_LINES);
                  {
                        int xMin = 0;
                        int xMax = 10;
                        gl.glColor3f(1f, 0f, 0f);

                        for (int x = xMin; x <= xMax; x++)
                        {
                              gl.glVertex3f(x, -1, 0f);
                              gl.glVertex3f(x, +1, 0f);

                        }

                        gl.glVertex3f(0f, 0f, 0f);
                        gl.glVertex3f(4f, 4f, 4f);

                  }
                  gl.glEnd();

            }
            gl.glPopMatrix();

      }

      public void reshape(
            GLDrawable arg0,
            int arg1,
            int arg2,
            int arg3,
            int arg4)
      {
            //System.err.println("RESHAPE THREAD: " + Thread.currentThread()); 
            GL gl = arg0.getGL();

            System.out.println(
                  "Vectrix.init(): GL reshape event "
                        + arg1
                        + " "
                        + arg2
                        + " "
                        + arg3
                        + " "
                        + arg4);

            if (setCameraInReshape)
            {
                  //   l/r  b/t  near/far  
                  gl.glMatrixMode(GL.GL_PROJECTION);
                  gl.glOrtho(0, 4, 0, 3, -8, 8);
            }

      }

      public void displayChanged(GLDrawable arg0, boolean arg1, boolean arg2)
      {}
}

(stack trace unchanged from the above).

The forum doesn’t like posting the whole of the Gears source in one, so I uploaded the class and stack trace here: studenti.lboro.ac.uk/~cojc5/Temp/GearsModified.zip

After some experimentation, I now believe that my previous bug report is in fact not a bug. If you change all the calls around glOrtho() to look like this:

gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.glOrtho(…)
gl.glMatrixMode(gl.GL_MODELVIEW)

the app works correctly regardless of the value of setCameraInReshape.

Without the call to glLoadIdentity, the camera matrix is being incrementally adjusted each frame, because glOrtho() creates a projection matrix and multiplies it by the current matrix.

Also, without setting the glMatrixMode back to ModelView, your glTranslate/rotate operations were affecting the camera instead of the vertices.

Based on this discovery, I have declared that issue not-a-bug.

However, there was a bug in the DebugGL. I ran the JoglTest program you sent me and receive no errors at all from DebugGL. Then I realized that I was running in a source base that has been modified since the code was posted on java.net. There was a bugfix in DebugGL that was accidentally not merged into the java.net CVS tree; that bug would cause incorrect GLExceptions dealing with glBegin/glEnd.

I have fixed this in version 1.2 of BuildComposablePipeline.java; please update your CVS tree and rebuild. Sorry for the inconvenience!

-chris

aha… that makes much more sense ;D That problem with the DebugGL had me chasing after the wrong things. Good to know the CVS has a fixed version now - thanks!