picking problem

Hey all,

I’m still trying to make the triangular elements of a mesh highlight when my mouse hovers over them. This used to work, but somehow I broke it and no matter where I put the mouse, I’m always getting one hit, even when the mouse is off the model. I only have one object in my screen that I look at.

Does anyone see anything wrong w/ what I have below.


public void mouseMoved(MouseEvent me) {
      currMouseX = me.getX();
      currMouseY = me.getY();

      cmd = SELECT;
      this.gldrawable.display();

      // Now draw the hits visually.
      cmd = UPDATE;
      this.gldrawable.display();
}

During normal rendering mode, my GLEventListener’s display() method draws models as such …


Took out display() method so as not to confuse, new display() is down below.

And here’s my processHits method …


public void processHits(int hits, IntBuffer buffer) {
   boolean debug = true;
		
   int offset = 0;
   int names;
   float z1, z2;

   // problem, number of hits is always 1
   for (int i = 0; i < hits; i++) {
      names = buffer.get(offset);
      offset++;
      z1 = (float) buffer.get(offset) / 0x7fffffff;
      offset++;
      z2 = (float) buffer.get(offset) / 0x7fffffff;
      offset++;

      for (int j = 0; j < names; j++) {
         // problem, active_id is always 0
         active_id = buffer.get(offset);
         
         offset++;
      }
   }
}

Any help much appreciated.

Ok, I’ve gone over this code a million times and I beleive it should work. The code is very similiar to this code here … http://www.sm.luth.se/~david/classes/smm009/TestPrograms/Picking.java … and that works on my machine.

Does anyone have any debug ideas as to why my code isn’t working?

It looks like you’re losing the contents of your projection matrix when setting up the pick matrix. See this thread for a similar discussion.

Yeah, I read that tread well. And my code was taken directly from the example given in that thread (same as the link I posted). What’s interesting is that, the example which works on my box doesn’t use the gluPerspective(…) method (which is where that thread seemed to end up). So I didn’t add that (just like the example), or see any need for it cause the pick matrix is multiplied onto the current matrix stack which, AFAIK, is correct and all that’s needed.

I think your right that I’m losing my gluPickMatrix(), but I can’t understand how right now.

It also looks like you’re leaving the modelview matrix with its old contents during the pick operation. I would recommend you put only the pick matrix (plus any orthographic or perspective projection) into the projection matrix and put your lookAt results into the modelview matrix, as in your update case.

I made that change, but it didn’t make a difference. Are there any routines maybe I’m not seeing that I can use to help debug what’s going on?

My code now looks like this.


public void display(GLDrawable drawable) {
	GL gl = drawable.getGL();
	GLU glu = drawable.getGLU();
		
	float[] transf = new float[16];
	
	this.gldrawable = drawable;
		
	if (!selectedFile) {
		return;
	}
		
	eyeZ = centroid.getZ() < 0 ? centroid.getZ() * -2: centroid.getZ() * 2;

	switch (cmd) {
		case UPDATE:
		   	// clear the window
			gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
			
			// reset the modelview matrix
			gl.glColor3f(1.0f, 1.0f, 1.0f);
			gl.glMatrixMode(GL.GL_MODELVIEW);
			gl.glLoadIdentity();

			// viewing transformation
			glu.gluLookAt(
				centroid.getX() + xTrans, 
				centroid.getY() + yTrans, 
				centroid.getZ() + zTrans + eyeZ,
				centroid.getX() + xTrans, 
				centroid.getY() + yTrans, 
				centroid.getZ(), 
				0.0, 1.0, 0.0);
				
			// model tranformation
			xScale = yScale < xScale ? yScale: xScale;
			yScale = xScale < yScale ? xScale: yScale;

			{
				gl.glScalef(xScale, yScale, 0.0f);
				arcBall.transform.get(transf);
				gl.glMultMatrixf(transf);
				drawModel(drawable, gl);
			}
			
			break;

		case SELECT:
			int hits = 0;
			int buffSize = 512;
			int[] viewPort = new int[4];
			double x = (double) currMouseX, y = (double) currMouseY;
			
			IntBuffer selectBuffer = BufferUtils.newIntBuffer(buffSize);
			gl.glSelectBuffer(buffSize, selectBuffer);
			gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort);
			
			gl.glRenderMode(GL.GL_SELECT);
			
			gl.glInitNames();
			gl.glPushName(0);
			
			gl.glMatrixMode(GL.GL_MODELVIEW);
			gl.glLoadIdentity();
			
			glu.gluLookAt(
			    centroid.getX() + xTrans, 
			    centroid.getY() + yTrans, 
			    centroid.getZ() + zTrans + eyeZ,
			    centroid.getX() + xTrans, 
			    centroid.getY() + yTrans, 
			    centroid.getZ(), 
			    0.0, 1.0, 0.0);
			
			// Save the current projection because we have a new
			// clipping volume around the mouse cursor now.
			gl.glMatrixMode(GL.GL_PROJECTION);
			gl.glPushMatrix();
			gl.glLoadIdentity();
			
			// Establish the new clipping pane. Multiplies the current 
			// projection matrix by the picking matrix.
			glu.gluPickMatrix(x, (double) viewPort[3] - y,
				3.0d, 3.0d, viewPort);

			gl.glOrtho(-winWidth / 2, winWidth / 2, -winHeight / 2, winHeight / 2, 100, -100);

			xScale = yScale < xScale ? yScale: xScale;
			yScale = xScale < yScale ? xScale: yScale;

			{
				gl.glScalef(xScale, yScale, 0.0f);
				arcBall.transform.get(transf);
				gl.glMultMatrixf(transf);
				drawModel(drawable, gl);
			}

			gl.glMatrixMode(GL.GL_PROJECTION);
			gl.glPopMatrix();
			hits = gl.glRenderMode(GL.GL_RENDER);
			processHits(hits, selectBuffer);
			gl.glMatrixMode(GL.GL_MODELVIEW);
			break;
	}
	
	cmd = UPDATE;
	
	return;
}

Showing reshape because of the glOrtho here.


	public void reshape(GLDrawable drawable, int x, int y, int width,
			int height)
	{
		GL gl = drawable.getGL();
		GLU glu = drawable.getGLU();
		
		winWidth = width;
		winHeight = height;
		
		gl.glViewport(0, 0, width, height);

		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		
		gl.glOrtho(-width / 2, width / 2, -height / 2, height / 2, 100, -100);

		if (selectedFile) {
			initScaleXY();			
		}
		
		arcBall.setBounds(width, height);
		
		return;
	}

You’re still overwriting your current projection matrix with the pick matrix by pushing a matrix on the projection stack and calling glLoadIdentity. Look again at the Picking.java case above. After calling gluPickMatrix the author calls gluOrtho2D. You need to multiply the pick matrix by your usual projection matrix.

Thank you. I added a glOrtho (modified the code above as well as added my reshape() method) and I just copied the glOrtho from that.

Now my stuff is highlighting, but it’s off to the left and below the cursor, like by about 50 pixels. No matter where I move my cursor, the picking seems to occur below and left of the mouse.

I’m guessing it’s got something to do w/ the values I have in glOrtho, but anything else I put in there really messes up my model. Any idea what is causing this?

And I should add that winWidth and winHeight are just class variables to get that width and height into glOrtho in the SELECT case.

In your select case you’re manipulating the projection matrix with the arcball rather than the modelview matrix as in your rendering code. Both code paths must perform identical matrix operations aside from the call to gluPickMatrix. Go through line by line to confirm this and see whether it fixes your problem.