A picking problem

Hello,
I want to draw some boxes , and then let the user pick a box. I’m using glLoadName, and it works ok, but… It seems that what is actually drawn is a bit closer then what is “drawn” for the selection process.
I think that’s the problem because when I try to select something where it would have been if it was a bit far away, it gives me a hit, and when I try to select a box in it’s margins (which wouldn’t have been drawn if it was more far away) it doesn’t give me a hit.
Does anyone knows what can be wrong here?
Thanks a lot in advance, Libby

Are you sure you are using the same projection matrix and drawing code for the picking as for drawing. It sounds like there might be some variance between the two.

well, I think so… the problem is I took some bits and pieces from various sample programs, but I just can’t find the problem.

This is my code ( it’s in Delphi):

procedure GLInit;
const
light0_position:TGLArrayf4=( 0.0, 8.0,6.0, 0.5);
ambient: TGLArrayf4=( 0.1,0.1,0.1,0.5);
diffuse: TGLArrayf4=( 0.9,0.9,0.9,0.8);
begin

// set viewing projection */
glMatrixMode(GL_PROJECTION);
glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);
// position viewer */
glMatrixMode(GL_MODELVIEW);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);

glLightfv(GL_LIGHT0, GL_POSITION, @light0_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, @ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, @Diffuse);

glEnable(GL_LIGHT0);


glColor4f(1.0,1.0,1.0,0.0);			// Full Brightness, 50% Alpha ( NEW )
glBlendFunc(GL_SRC_ALPHA,GL_ONE);		// Blending Function For Translucency Based On Source Alpha Value ( NEW )
glEnable(GL_BLEND);		// Turn Blending On
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);

end;

procedure TForm1.Draw(mode : integer);

var
i : integer;
begin

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glEnable(GL_NORMALIZE);
glShadeModel(GL_FLAT);
glCullFace(GL_BACK);

glLoadIdentity;

glTranslatef(0.0, 0.0, -10);
glRotatef(angleX, 1.0, 0.0, 0.0);
glRotatef(angleY, 0.0, 1.0, 0.0);

glPushMatrix;

for i:=1 to nextBox-1 do
begin
glPolygonMode(GL_FRONT_AND_BACK,GL_Line);
glColor4f(0,0, 0,1);
if mode = GL_SELECT then glLoadName(i);
glBegin(GL_QUADS);
// Back Face
glNormal3f(0,0,-1); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 4 (Front)
// Front Face
glNormal3f(0,0,1); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 4 (Front)

  // Top Face
  glNormal3f(0,1,0);					// Normal Pointing Towards Viewer

{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 4 (Front)
// Bottom Face
glNormal3f(0,-1,0); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 4 (Front)
// Right face
glNormal3f(1,0,0); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 4 (Front)
// Left Face
glNormal3f(-1,0,0); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 4 (Front)
glend();

glPolygonMode(GL_FRONT_AND_BACK,GL_Fill);
glColor4f(Cubes[i].color.red, Cubes[i].color.Green, Cubes[i].color.blue, Cubes[i].color.Alpha);

glBegin(GL_QUADS);
    // Back Face
  glNormal3f(0,0,-1);					// Normal Pointing Towards Viewer

{left top} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 4 (Front)
// Front Face
glNormal3f(0,0,1); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 4 (Front)

  // Top Face
  glNormal3f(0,1,0);					// Normal Pointing Towards Viewer

{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 4 (Front)
// Bottom Face
glNormal3f(0,-1,0); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 4 (Front)
// Right face
glNormal3f(1,0,0); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].frontRightBottomPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].frontRightBottomPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 4 (Front)
// Left Face
glNormal3f(-1,0,0); // Normal Pointing Towards Viewer
{left top} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].backLeftTopPoint.y, Cubes[i].backLeftTopPoint.z); // Point 1 (Front)
{right top} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].backLeftTopPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 2 (Front)
{right bottom} glVertex3f( Cubes[i].backLeftTopPoint.x, Cubes[i].frontRightBottomPoint.y, Cubes[i].frontRightBottomPoint.z); // Point 3 (Front)
{left bottom} glVertex3f(Cubes[i].backLeftTopPoint.x,Cubes[i].frontRightBottomPoint.y, Cubes[i].backLeftTopPoint.z); // Point 4 (Front)
glend();

end;
glPopMatrix;
SwapBuffers(wglGetCurrentDC);
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
glPushMatrix;
Draw(GL_RENDER);
glPopMatrix;
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
selectBuf: array[0…BUFSIZE-1] of GLUint;
hits: GLint;
i, j, k, names: Integer;
Viewport: TViewPortArray;
msg: String;
begin

glGetIntegerv(GL_VIEWPORT, @viewport);

// Assign a selection buffer and switch to selection mode.
glSelectBuffer(BUFSIZE, @selectBuf);
glRenderMode(GL_SELECT);

{ Init the name stack and push something meaningless on it. An empty stack
would mess things up once we start using glLoadName(). }
glInitNames;
glPushName(1000);

// Set the “viewing volume” used for the picking.
glMatrixMode(GL_PROJECTION);
glPushMatrix;
glLoadIdentity;

gluPickMatrix(x, viewport[3]-y, 1, 1, viewport);
gluPerspective(45.0,  (viewport[2]-viewport[0])/(viewport[3]-viewport[1]), 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);						// Select The Modelview Matrix

Draw(GL_SELECT);
glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix

glPopMatrix;
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
(*
glPopName;
glFinish;
*)
// When switching back to GL_RENDER, glRenderMode returns the number of selection hits.
hits := glRenderMode(GL_RENDER);
msg := 'Hits: '+ IntToStr(hits) + #13#10;

{ Process the selection records that are now in selectBuf.
Each record consists of the following (integer) values:
- The number of names on the stack at the time of the hit.
- The minimum and maximum Z values of the primitives inside the viewing volume.
- The contents of the name stack, bottom-up. }
j := 0;
for i := 0 to hits-1 do
begin
// Number of names (always 1 if you use glLoadName instead of glPushName).
names := selectBuf[j];
msg := msg + #13#10 + ’ Number of names for hit = ’ + IntToStr(names);
INC(j);
// Z values (always 0 in this program, don’t know why?).
msg := msg + #13#10 + 'z1 = ’ + IntToStr(selectBuf[j]);
INC(j);
msg := msg + #13#10 + 'z2 = ’ + IntToStr(selectBuf[j]);
INC(j);
// Contents of name stack:
msg := msg + #13#10 + 'Name(s): ';
for k := 0 to names-1 do
begin
msg := msg + IntToStr(selectBuf[j]) + ’ ';
INC(j);
end;
msg := msg + #13#10;
end;
ShowMessage(msg);

end;

Thanks a lot for your patience, Libby

I think that the problem might be with the line:
gluPerspective(45.0, (viewport[2]-viewport[0])/(viewport[3]-viewport[1]), 0.1, 100.0);

but I don’t know what I should write.

Libby

Originally posted by libby:

gluPerspective(45.0, (viewport[2]-viewport[0])/(viewport[3]-viewport[1]), 0.1, 100.0);

I think you are right. You need to use the same projection both when you render the scene and when you try to pick an object. Earlier in your code you use:

glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);

to set up the projection. These should be the same. Swap the gluPerspective line into where you use glFrustum (or vice versa) and you will render the same scene which you later use to pick.

jimmi