Hello, I was digging into picking the other day when I found an example about picking using 4 snowmen.
The tutorial was written in C++ so I converted it to JOGL 2.0 code but I ran into some trouble.
When I click 3 out of 4 snowmen I get 2 hits, instead of 1. How ever the eventual number of the snowman clicked
then matches (1 to 3). When i click the first snowman (bottom left), I get only 1 hit, like it is supposed to be i think but
I still get the result that I clicked snowmen nr 1 (instead of 0). I attached code here. Does any1 have any idea what i do wrong?
Also every time i click on my screen, it blinks black for a second. Is this normal and is there any way to avoid this?
Thx
The JFRame class and other GUI stuff
package snowmanpicking;
import com.jogamp.opengl.util.FPSAnimator;
import java.awt.Dimension;
import java.awt.event.*;
import javax.media.opengl.*;
import javax.media.opengl.awt.GLJPanel;
import javax.swing.*;
/**
*
* @author Grand Poeba
*/
public class SnowmanFrame extends JFrame {
private GLJPanel gljPanel;
public SnowmanFrame(){
this.initGUI();
}
private void initGUI(){
// Choose the GL profile
GLProfile glp = GLProfile.getMaxFixedFunc();
// Configure the GL capabilities
GLCapabilities caps = new GLCapabilities(glp);
this.gljPanel = new GLJPanel(caps);
final Render r = new Render();
this.gljPanel.addGLEventListener(r);
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) return;
r.cursorX = e.getX();
r.cursorY = e.getY();
r.mode = GL2.GL_SELECT;
System.out.println("Swapped mode to GL_SELECT");
}
});
this.getContentPane().add(this.gljPanel);
this.setMinimumSize(new Dimension(800,600));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public GLJPanel getGLJPanel() {
return this.gljPanel;
}
public static void main (String[] args){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SnowmanFrame sf = new SnowmanFrame();
FPSAnimator animator = new FPSAnimator(sf.getGLJPanel(), 60);
animator.add(sf.getGLJPanel());
animator.start();
}
});
}
}
The actual renderer with picking code
package snowmanpicking;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.gl2.GLUT;
import java.nio.IntBuffer;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
/**
*
* @author Grand Poeba
*/
public class Render implements GLEventListener {
public static int cursorX, cursorY;
private float posX, posY, posZ, lookAtX, lookAtY, lookAtZ;
public static int mode, hits;
// Picking Stuff //
int BUFSIZE = 1024;
IntBuffer selectBuf = Buffers.newDirectIntBuffer(BUFSIZE);
// display list of our snowman
public static int snowman_display_list;
void processKeyboard(char key, int x, int y) {
System.out.printf("key: %d\n", key);
}
void picked(int name, int sw) {
System.out.printf("my name = %d in %d\n", name, sw);
}
void drawSnowMan(GL2 gl, GLUT glut) {
gl.glColor3f(1.0f, 1.0f, 1.0f);
// Draw Body
gl.glTranslatef(0.0f, 0.75f, 0.0f);
glut.glutSolidSphere(0.75f, 20, 20);
// Draw Head
gl.glTranslatef(0.0f, 1.0f, 0.0f);
glut.glutSolidSphere(0.25f, 20, 20);
// Draw Eyes
gl.glPushMatrix();
gl.glColor3f(0.0f, 0.0f, 0.0f);
gl.glTranslatef(0.05f, 0.10f, 0.18f);
glut.glutSolidSphere(0.05f, 10, 10);
gl.glTranslatef(-0.1f, 0.0f, 0.0f);
glut.glutSolidSphere(0.05f, 10, 10);
gl.glPopMatrix();
// Draw Nose
gl.glColor3f(1.0f, 0.5f, 0.5f);
gl.glRotatef(0.0f, 1.0f, 0.0f, 0.0f);
glut.glutSolidCone(0.08f, 0.5f, 10, 2);
}
int createDL(GL2 gl) {
int snowManDL;
// Create the id for the list
snowManDL = gl.glGenLists(1);
gl.glNewList(snowManDL, GL2.GL_COMPILE);
drawSnowMan(gl, new GLUT());
gl.glEndList();
return (snowManDL);
}
void draw(GL2 gl) {
// Draw ground
gl.glColor3f(0.9f, 0.9f, 0.9f);
gl.glBegin(GL2.GL_QUADS);
gl.glVertex3f(-100.0f, 0.0f, -100.0f);
gl.glVertex3f(-100.0f, 0.0f, 100.0f);
gl.glVertex3f(100.0f, 0.0f, 100.0f);
gl.glVertex3f(100.0f, 0.0f, -100.0f);
gl.glEnd();
// Draw 4 SnowMen
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
gl.glPushMatrix();
gl.glPushName(i * 2 + j);
gl.glTranslated(i * 3.0, 0, -j * 3.0);
gl.glCallList(snowman_display_list);
gl.glPopName();
gl.glPopMatrix();
}
}
}
@Override
public void dispose(GLAutoDrawable drawable) {
}
@Override
public void display(GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
if (mode == GL2.GL_SELECT) startPicking(gl);
gl.glLoadIdentity();
GLU glu = new GLU();
glu.gluLookAt(posX, posY, posZ, lookAtX, lookAtY, lookAtZ, 0.0f, 1.0f, 0.0f);
draw(gl);
if (mode == GL2.GL_SELECT) stopPicking(gl);
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
final GL2 gl = drawable.getGL().getGL2();
GLU glu = new GLU();
float ratio;
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if (height == 0) height = 1;
ratio = 1.0f * width / height;
// Reset the coordinate system before modifying
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
// Set the viewport to be the entire window
gl.glViewport(0, 0, width, height);
// Set the clipping volume
glu.gluPerspective(45, ratio, 0.1, 1000);
// setting the camera now
gl.glMatrixMode(GL2.GL_MODELVIEW);
}
@Override
public void init(GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
posX = 1.5f;
posY = 3.75f;
posZ = 3f;
lookAtX = 1.5f;
lookAtY = 1.75f;
lookAtZ = 0f;
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glEnable(GL2.GL_CULL_FACE);
snowman_display_list = createDL(gl);
// enable vsync
gl.setSwapInterval(1);
}
void startPicking(GL2 gl) {
System.out.println("Start Picking");
IntBuffer viewport = Buffers.newDirectIntBuffer(4);
float ratio;
gl.glSelectBuffer(BUFSIZE, selectBuf);
gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport);
gl.glRenderMode(GL2.GL_SELECT);
gl.glInitNames();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
GLU glu = new GLU();
glu.gluPickMatrix(cursorX, viewport.get(3) - cursorY, 5, 5, viewport);
ratio = (float) (viewport.get(2) + 0.0f) / (float) viewport.get(3);
glu.gluPerspective(45, ratio, 0.1, 1000);
gl.glMatrixMode(GL2.GL_MODELVIEW);
}
void stopPicking(GL2 gl) {
System.out.println("Stop Picking");
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glFlush();
hits = gl.glRenderMode(GL2.GL_RENDER);
if (hits > 0) {
System.out.println("# of hits: " + hits);
processHits(hits, selectBuf);
} else {
System.out.println("no hits");
}
mode = GL2.GL_RENDER;
}
void processHits(int hits, IntBuffer buffer) {
int name = -1;
int i = 0, nrOfHits = 0;
while(nrOfHits < hits && i < BUFSIZE) {
if(buffer.get(i) > 0){
name = buffer.get(i);
nrOfHits++;
}
i++;
}
if (name < 0) {
System.out.printf("You didn't click a snowman!");
} else {
System.out.printf("You picked snowman ");
System.out.printf("%d ", name);
}
System.out.printf("\n");
}
}