GL2 2D animation w/o GLUT... I think I almost got it?

I’ve refactored the colored dots example and am trying to animate it, en route to writing a minimal game engine for my weird ideas.

I’m using GL2 in hopes that once I get comfy with it, I’ll be in a good position to backport for droid and then go from there into the better stuff in modern GL.

So that’s why I’m using these methods. I’m just not sure what to do between successfully painting some stuff on the screen, and drawing the next frame.

Status in a nutshell: if I comment out the last line in init() (which creates a listener in my time object calling my display method) everything draws once, stays put, another object’s time listener shows the current tick count, the canvas scales (as do the dots), some text shows up – all’s good. When I register the tick listener to animate the screen, I get an access violation when I try to call my first gl command… in the exact same display method that works fine on initial render.

This makes me think I’m, like, one line off somewhere, or something. Here’s the renderer… can anyone give me a targeted clue? Thank you!

import java.awt.Color;
import java.awt.Font;
import java.util.Random;

import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.util.awt.TextRenderer;

import us.nathanhawks.t.core.GameTime;
import us.nathanhawks.t.core.TickEventAction;
import us.nathanhawks.t.util.TLibGL2;

public class TestingGLCanvas implements GLEventListener {

  int defaultViewWidth, defaultViewHeight;
  dots dots; // class described at bottom of this file
  GameTime time; // only way this is the problem is if 50ms is too fast a tick for GL2/GTX970M, so, I'm betting it's fine
  update_listener dotsListener; // class described at bottom of this file

  public TestingGLCanvas(GameTime t) {
    time = t;
  }
  public void init() {}
  public void display() {}
  public void dispose() {}
  public void reshape() {}
  
  @Override
  public void init(GLAutoDrawable drawable) {
    defaultViewWidth = 800;
    defaultViewHeight = 568;
    TLibGL2 tgl = TLibGL2.getInstance();
    tgl.initWindowed2DCanvas(drawable, defaultViewWidth, defaultViewHeight);
    dots = new dots();
    dotsListener = new update_listener(time, dots); // if I comment this out, everything works, there's just no animation
  }
  @Override
  public void display(GLAutoDrawable drawable) {
    GL2 gl = drawable.getGL().getGL2();
    gl.glClear(GL.GL_COLOR_BUFFER_BIT);
    dots.setGL(gl);
    // Draw the initial position
    dots.draw(false);

    // woo I can make text
    Font f = new Font("Baby Kruffy", Font.PLAIN, 36);
    TextRenderer tr = new TextRenderer(f, true, true, null, true);
    String t = "Have some words, screen!";
    tr.setColor(Color.LIGHT_GRAY);
    tr.beginRendering(drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
    tr.draw(t,  50,  50);
    tr.endRendering();

  }
  @Override
  public void dispose(GLAutoDrawable drawable) {
    // TODO Auto-generated method stub
    
  }
  @Override
  public void reshape(GLAutoDrawable drawable, int x, int y, int width,
      int height) {
    // TODO Auto-generated method stub
    
  }
  
  public int[] jitterXY(int x, int y) {
    // this function's all good; I can displace on first render just fine
    int[] rv = new int[2];
    int xo, yo;
    Random rn = new Random();
    xo = rn.nextInt(8) - 4;
    yo = rn.nextInt(8) - 4;
    rv[0] = x + xo;
    rv[1] = y + yo;
    return rv;
  }
  private class dots {
    GL2 gl;
    public dots() { }
    public void setGL(GL2 g) { gl = g; }
    public void draw(boolean doJitter) {
      float red = 0.0f;
      float green = 0.0f;
      float blue = 0.0f;
	  // no matter what I've added for troubleshooting (flush, push/pop, try/catch) no change;
	  // works fine without the listener, crashes (access violation) while trying to draw the second frame with it
      try {
        gl.glFlush();
        gl.glPushMatrix();
  
        gl.glPointSize(5.0f);
  
        for (int i=0; i<50; i++) {
  
            red -= .09f;
            green -= .12f;
            blue -= .15f;
  
            if (red < 0.15) red = 1.0f;
            if (green < 0.15) green = 1.0f;
            if (blue < 0.15) blue = 1.0f;
  
            gl.glColor3f(red, green, blue);
  
            int x = i*10;
            int y = 284;
            if (doJitter) {
              int[] afterOffsets = jitterXY(x, y);
              x = afterOffsets[0];
              y = afterOffsets[1];
            }
            gl.glBegin(GL.GL_POINTS);
            gl.glVertex2i(x, y);
            gl.glEnd();
            gl.glPopMatrix();
        } 
      } catch (GLException e) {
          System.out.println(e.getMessage());
          return;
      }
      
    }
  }
  public class update_listener extends TickEventAction {
    public dots dots;
    public update_listener(GameTime t, dots d) { super(t); dots = d; }
    public void eventAction() {
      try {
        dots.draw(true);
      } catch (GLException e) {
        String s = e.getMessage();
        System.out.println(s);
      }
    }
    
  }
}

Ok, it occurs to me that I’m working with a GL2 object that might have expired… but getting a fresh version isn’t helping.

I changed the eventAction in the update listener:

    public void eventAction() {
      dots.setGL(TLibGL2.getInstance().getExistingCanvas().getGL().getGL2()); // <----- getExistingCanvas returns the GLCanvas which is successfully created and drawn upon prior to this
      try {
        dots.draw(true);
      } catch (GLException e) {
        String s = e.getMessage();
        System.out.println(s);
      }

Nothing’s changed; it’s still getting into the renderer and having a fit at the first sign of a GL command.

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j jogamp.opengl.gl4.GL4bcImpl.dispatch_glFlush1(J)V+0
j jogamp.opengl.gl4.GL4bcImpl.glFlush()V+38
j us.nathanhawks.t.test.TestingGLCanvas$dots.draw(Z)V+11
j us.nathanhawks.t.test.TestingGLCanvas$update_listener.eventAction()V+26
j us.nathanhawks.t.core.GameTime.doTick()V+24
j us.nathanhawks.t.core.GameTime.access$0(Lus/nathanhawks/t/core/GameTime;)V+1
j us.nathanhawks.t.core.GameTime$1.run()V+4
j java.util.TimerThread.mainLoop()V+221
j java.util.TimerThread.run()V+1
v ~StubRoutines::call_stub

The relevant code:

private class dots {
    GL2 gl;
    public dots() { }
    public void setGL(GL2 g) { gl = g; }
    public void draw(boolean doJitter) {
      float red = 0.0f;
      float green = 0.0f;
      float blue = 0.0f;
      try {
        gl.glFlush();
        // ... kersplat

Is my approach just wrong? I keep thinking all I have to do is blank the screen and start drawing again, as I’ve read on stacktrace… do I have to recreate the GLCanvas itself for every frame?

I found a pdf posted on a college website that answered it.

In case it ever disappears…


GLProfile glp=GLProfile.getDefault();
GLCapabilities caps = new GLCapabilities(glp);
canvas = new GLCanvas(caps); // canvas is a class varible of type GLCanvas
// here the user interface should be created and
// the canvas added to the window frame.
canvas.addGLEventListener(this);
FPSAnimator animator = new FPSAnimator(canvas, 60);
animator.start();

The second param on the FPSAnimator constructor is your target FPS.

It’s serious about the sequence of events: I’m not sure whether it was attaching the listener, or initializing the animator, but doing it before attaching the canvas to the UI wasn’t working. Once you properly initialize the animator, the display() method in your GLEventListener will fire 60 times per second like magic.