Color picking in GLJPanel
Posted by copeg on Apr 19, 2018; 7:57pm
URL: https://forum.jogamp.org/Color-picking-in-GLJPanel-tp4038826.html
Trying to implement picking using the color based approach - render each unique object's primitives as a unique color. Disable autoswap of the component, then when picking render the unique colors to the back buffer and use glReadPixels of the back buffer to get the color under the mouse without swapping the buffer. The issue arises when I use a Swing GLJPanel - the back buffer gets rendered during the picking phase eg the unique colors are rendered onto the JPanel (rather than rendered to the back buffer and not seen again).
JOGL 2.3.1, Windows 7
Demo below with triangle (click on the triangle as see the green picking color). Any ideas? FWIW this works with a GLCanvas, but would very much like to avoid using a heavyweight component in my application
import java.awt.Color;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.lang.reflect.InvocationTargetException;
import java.nio.FloatBuffer;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLJPanel;
/**
* Demo program to demonstrate clearing upon rotation
* @author Greg Cope
*
*/
public class SwingJOGLRotationClear implements GLEventListener {
final GLProfile profile = GLProfile.get( GLProfile.GL2 );
GLCapabilities capabilities = new GLCapabilities( profile );
{
capabilities.setDoubleBuffered(true);
capabilities.setSampleBuffers(true);
capabilities.setFBO(true);
}
// The canvas
final GLJPanel glcanvas = new GLJPanel( capabilities ){
@Override
public void swapBuffers(){
//Log when buffers are swapped
System.out.println("Swapping buffers");
super.swapBuffers();
}
};
private Point mouseDownPoint = null;
public static DisplayMode dm, dm_old;
private float rquad = 0.0f;
private volatile boolean picking = false;
private MouseEvent pickingEvent = null;
private int glWidth = -1;
private int glHeight = -1;
@Override
public void display( GLAutoDrawable drawable ) {
System.out.println("Rendering: " + picking);
final GL2 gl = drawable.getGL().getGL2();
gl.glMatrixMode( GL2.GL_MODELVIEW );
gl.glLoadIdentity();
gl.glClearColor(0f, 0f, 0f, 0f);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );
gl.glEnable(GL2.GL_LIGHTING);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glEnable(GL2.GL_LIGHTING);
gl.glEnable(GL2.GL_LIGHT0);
gl.glEnable(GL2.GL_NORMALIZE);
gl.glDisable(GL2.GL_CULL_FACE);
float[] position = new float[]{0f,0f,50f,0f};
float[] ambient = new float[]{ 0.1f,0.1f,0.1f,0f};
float[] diffuse = new float[]{ 0.9f,0.9f,0.9f,0f };
float[] specular = new float[]{ 0.5f,0.5f,0.5f,0f };
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, position, 0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, ambient, 0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, diffuse, 0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_SPECULAR, specular, 0);
float[] spec = new float[]{1f,1f,1f};
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, spec, 0);
gl.glMaterialf(GL2.GL_FRONT, GL2.GL_SHININESS, 100);
gl.glEnable(GL2.GL_LIGHTING);
if ( picking ){
System.out.println("drawing to back buffer");
gl.glDrawBuffer(GL2.GL_BACK);
gl.glDisable(GL2.GL_LIGHTING);
gl.glColor3f(0f,1f,0f);
}else{
gl.glColor3f(1f,0f,0f);
}
float z = -1.5f;
gl.glTranslated(0, 0, z);
gl.glRotatef(rquad, 0f, 1f, 0f);//1.0f, 1.0f, 1.0f);
gl.glTranslated(0, 0, -z);
float[] mat = new float[]{1f,0,0,1f};
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, mat, 0);
gl.glNormal3f(0,0,1);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glVertex3f(-1f, 0, z);
gl.glVertex3f(0f,1f, z);
gl.glVertex3f(1f,0f,z);
gl.glEnd();
if ( picking ){
System.out.println("Picking from back buffer");;
FloatBuffer pixels = FloatBuffer.allocate(4);
gl.glReadBuffer(GL2.GL_BACK);
gl.glReadPixels(pickingEvent.getX(), glHeight - pickingEvent.getY(),
1, 1, GL2.GL_RGBA, GL2.GL_FLOAT, pixels);
Color color = new Color(pixels.get(0), pixels.get(1), pixels.get(2));
System.out.println("Pickied color: " + color);
picking = false;
}else{
drawable.swapBuffers();
}
}
@Override
public void dispose( GLAutoDrawable drawable ) {
}
@Override
public void init( GLAutoDrawable drawable ) {
glcanvas.setAutoSwapBufferMode(false);
final GL2 gl = drawable.getGL().getGL2();
gl.glShadeModel( GL2.GL_SMOOTH );
gl.glClearColor( 0f, 0f, 0f, 0f );
gl.glClearDepth( 1.0f );
gl.glShadeModel( GL2.GL_SMOOTH );
gl.glEnable( GL2.GL_DEPTH_TEST );
gl.glDepthFunc( GL2.GL_LEQUAL );
gl.glHint( GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST );
}
@Override
public void reshape( GLAutoDrawable drawable, int x, int y, int width, int height ) {
final GL2 gl = drawable.getGL().getGL2();
if( height <= 0 )
height = 1;
glWidth = width;
glHeight = height;
gl.glViewport( 0, 0, width, height );
gl.glMatrixMode( GL2.GL_PROJECTION );
gl.glLoadIdentity();
gl.glFrustum(-1, 1, -1, 1,1, 100);
}
public static void main( String[] args ) throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(new Runnable(){
@Override
public void run() {
final SwingJOGLRotationClear demo = new SwingJOGLRotationClear();
demo.glcanvas.setAutoSwapBufferMode(false);//disable auto swap
/*
* Listeners for draggin
*/
demo.glcanvas.addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e){
demo.mouseDownPoint = e.getPoint();
demo.pickingEvent = e;
}
@Override
public void mouseClicked(MouseEvent e){
demo.picking = true;
demo.glcanvas.repaint();
}
});
demo.glcanvas.addMouseMotionListener(new MouseMotionAdapter(){
@Override
public void mouseDragged(MouseEvent e){
demo.rquad += demo.mouseDownPoint.getX() - e.getX();
demo.mouseDownPoint = e.getPoint();
demo.glcanvas.repaint();
}
});
demo.glcanvas.addGLEventListener( demo );
demo.glcanvas.setPreferredSize( new Dimension(400, 400) );
final JFrame frame = new JFrame ( "Demo" );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add( demo.glcanvas );
frame.setSize( frame.getContentPane().getPreferredSize() );
frame.setVisible( true );
}
});
}
}