How to do Picking with GLJpanel

I have implemented a picking in my application, using the GLCanvas, and calling display.

I try to change with a GLJPanel, but the picking doesn’t wotk any more.

The problem seem to be, calling display on GLJPanel, doesn’t call the display of the listener.

What’s the solution ?

Could be a bug in the GLJPanel implementation. Could you post some code or file a bug and attach a test case?

Hi,

I just use the Picking code, and update it.
The problem is calling display on GLJPanel, will call asyncronously display.

Using GLCanvas we have:
call display before
in display
in display out
call display after

With GLJPanel we have:
call display before
call display after
in display
in display out

The sample code:
package com.type3.osg.render.jogl.test;

//=================================================================================
// Picking 0.2 (Thomas Bladh)
//=================================================================================
// A simple picking example using java/jogl. This is far from a complete solution
// but it should give you an idea of how to include picking in your assigment
// solutions.
//
// Notes: * Based on example 13-3 (p 542) in the “OpenGL Programming Guide”
// * This version should handle overlapping objects correctly.
//---------------------------------------------------------------------------------
import java.awt.;
import java.awt.event.
;
import java.awt.Canvas.;
import java.util.
;
import net.java.games.jogl.*;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

public class Picking
{

  // Change to GLCanvas, GLJPanel...

// boolean mbUseGLJPanel = false;
boolean mbUseGLJPanel = true;

  public static void main(String[] args)
  {
        new Picking();
  }

  public static       GLDrawable drawable = null; 

  Picking()
  {
        Frame frame = new Frame("Picking Example");
        GLDrawableFactory factory = GLDrawableFactory.getFactory();
        GLCapabilities capabilities = new GLCapabilities();
        
        if (mbUseGLJPanel)
                          drawable = factory.createGLJPanel(capabilities);
        else  drawable = factory.createGLCanvas(capabilities);
        
        drawable.addGLEventListener(new Renderer());
        drawable.setNoAutoRedrawMode(false);
        
        frame.add( (Component)drawable);
        frame.setSize(400, 400);

// final Animator animator = new Animator(drawable);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
// animator.stop();
System.exit(0);
}
});
frame.show();

// animator.start();
}

  static class Renderer implements GLEventListener, MouseListener, MouseMotionListener
  {
        static final int NOTHING = 0, UPDATE = 1, SELECT = 2;
        int cmd = UPDATE;
        int mouse_x, mouse_y;

        private GL gl;
        private GLU glu;
        private GLDrawable gldrawable;

        public void init(GLDrawable drawable)
        {
              gl = drawable.getGL();
              glu = drawable.getGLU();
              this.gldrawable = drawable;
              gl.glEnable(GL.GL_CULL_FACE);
              gl.glEnable(GL.GL_DEPTH_TEST);
              gl.glEnable(GL.GL_NORMALIZE);
              gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
              drawable.addMouseListener(this);
              drawable.addMouseMotionListener(this);
        }

        public void reshape(GLDrawable drawable, int x, int y, int width, int height)
        {

              float h = (float)height / (float)width;
              gl.glViewport(0, 0, width, height);
              gl.glMatrixMode(GL.GL_PROJECTION);
              gl.glLoadIdentity();
              glu.gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);
        }

        public void display(GLDrawable drawable)
        {

System.err.println(“in display”);

              switch (cmd)
              {
              case UPDATE:
                    drawScene();
                    break;
              case SELECT:
                    int buffsize = 512;
                    double x = (double)mouse_x, y = (double)mouse_y;
                    int[] viewPort = new int[4];
                    int hits = 0;

                    IntBuffer selectBuffer = null;
                    ByteBuffer myBB = ByteBuffer.allocateDirect(buffsize*4);
                    myBB.order(ByteOrder.nativeOrder());
                    selectBuffer = myBB.asIntBuffer();


                    gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort);
                    gl.glSelectBuffer(buffsize, selectBuffer);

                    gl.glRenderMode(GL.GL_SELECT);
                    gl.glInitNames();
                    gl.glMatrixMode(GL.GL_PROJECTION);
                    gl.glPushMatrix();
                    gl.glLoadIdentity();
                    glu.gluPickMatrix(x, (double)viewPort[3] - y, 5.0d, 5.0d, viewPort);
                    glu.gluOrtho2D(0.0d, 1.0d, 0.0d, 1.0d);
                    drawScene();
                    gl.glMatrixMode(GL.GL_PROJECTION);
                    gl.glPopMatrix();
                    gl.glFlush();
                    hits = gl.glRenderMode(GL.GL_RENDER);
                    processHits(hits, selectBuffer);
                    cmd = UPDATE;
                    break;
              }

System.err.println(“in display out”);
}

        public void processHits(int hits, IntBuffer buffer)
        {
              System.out.println("---------------------------------");
              System.out.println(" HITS: " + hits);
              int offset = 0;
              int names;
              float z1, z2;
              for (int i = 0; i < hits; i++)
              {
                    System.out.println("- - - - - - - - - - - -");
                    System.out.println(" hit: " + (i + 1));
                    names = buffer.get(offset);
                    offset++;
                    z1 = (float)buffer.get(offset) / 0x7fffffff;
                    offset++;
                    z2 = (float)buffer.get(offset) / 0x7fffffff;
                    offset++;
                    System.out.println(" number of names: " + names);
                    System.out.println(" z1: " + z1);
                    System.out.println(" z2: " + z2);
                    System.out.println(" names: ");

                    for (int j = 0; j < names; j++)
                    {
                          System.out.print("       " + buffer.get(offset));
                          if (j == (names - 1))
                          {
                                System.out.println("<-");
                          }
                          else
                          {
                                System.out.println();
                          }
                          offset++;
                    }
                    System.out.println("- - - - - - - - - - - -");
              }
              System.out.println("---------------------------------");
        }

        public int viewPortWidth()
        {
              int[] viewPort = new int[4];
              gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort);
              return viewPort[2];
        }

        public int viewPortHeight()
        {
              int[] viewPort = new int[4];
              gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort);
              return viewPort[3];
        }

        public void drawScene()
        {
              gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

              // Colors
              float red[] =
                                                        {
                                                        1.0f, 0.0f, 0.0f, 1.0f};
              float green[] =
                                                              {
                                                              0.0f, 1.0f, 0.0f, 1.0f};
              float blue[] =
                                                         {
                                                         0.0f, 0.0f, 1.0f, 1.0f};

              // Red rectangle
              GLRectangleEntity r1 = new GLRectangleEntity(gl, glu);
              r1.x = 0.15f;
              r1.y = 0.25f;
              r1.w = 0.4f;
              r1.h = 0.4f;
              r1.c = red;
              r1.id = 10;
              r1.draw();

              // Green rectangle
              GLRectangleEntity r2 = new GLRectangleEntity(gl, glu);
              r2.x = 0.35f;
              r2.y = 0.45f;
              r2.w = 0.4f;
              r2.h = 0.4f;
              r2.c = green;
              r2.id = 20;
              r2.draw();

              // Blue rectangle
              GLRectangleEntity r3 = new GLRectangleEntity(gl, glu);
              r3.x = 0.45f;
              r3.y = 0.15f;
              r3.w = 0.4f;
              r3.h = 0.4f;
              r3.c = blue;
              r3.id = 30;
              r3.draw();

              gl.glFlush();
        }

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

        public void mousePressed(MouseEvent e)
        {
              cmd = SELECT;
              mouse_x = e.getX();
              mouse_y = e.getY();
              
              // call to do the pick
              System.err.println("call display before");
        drawable.display();
        System.err.println("call display after");

        }

        public void mouseEntered(MouseEvent e)
        {}

        public void mouseExited(MouseEvent e)
        {}

        public void mouseReleased(MouseEvent e)
        {}

        public void mouseClicked(MouseEvent e)
        {}

        public void mouseDragged(MouseEvent e)
        {}

        public void mouseMoved(MouseEvent e)
        {}

        public abstract class GLEntity
        {
              float x, y, z;
              float[] c;
              int id = 0;
              boolean outline = false;
              GL gl;
              GLU glu;
              public GLEntity(GL gl, GLU glu)
              {
                    this.gl = gl;
                    this.glu = glu;
              }

              public void draw()
              {
                    gl.glPushName(id);
                    _draw();
              }

              public abstract void _draw();
        }

        public class GLRectangleEntity extends GLEntity
        {
              float w = 0.1f;
              float h = 0.1f;
              public GLRectangleEntity(GL gl, GLU glu)
              {
                    super(gl, glu);
              }

              public void _draw()
              {
                    if (outline)
                    {
                          gl.glPolygonMode(GL.GL_FRONT, GL.GL_LINE);
                    }
                    else
                    {
                          gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
                    }

                    gl.glColor4fv(c);
                    gl.glBegin(GL.GL_POLYGON);
                    gl.glVertex3f(x, y, z);
                    gl.glVertex3f(x + w, y, z);
                    gl.glVertex3f(x + w, y + h, z);
                    gl.glVertex3f(x, y + h, z);
                    gl.glEnd();
              }
        }
  }

}

You’re right, the GLJPanel display() implementation wasn’t obeying its specification. When called from the AWT event queue thread, it was scheduling a repaint rather than performing the work immediately; I hadn’t known until now how to do this correctly. I’ve checked a change to JOGL’s CVS repository to fix this; it will be present in the next JOGL beta, or you can take an update and rebuild your own source tree. Thanks for pointing out this problem.