PDA

View Full Version : GL Picking



M109uk
27-05-2007, 11:05 AM
Hi all,

Im having a little trouble with GL Picking.. it works fine when there are 2 or more objects to select, how ever if i click in a space where there is no objects it always select the last object created.. heres a screenshot:

http://www.pulse-soft.oneuk.com/images/stories/prj_devilscube/dcse_glpick.jpg

I can select the left and the right faces without a problem, but if for example i click in the very bottom right cornour, the left face is always selected.

below is the code im using in the OnClick event of my mouse class:



procedure GLOnClick(const X,Y: Integer; const Button: TXGUIMouseButton);
var
selectBuff : Array Of Cardinal;
vp: TVector4i;
hits,SelectedName: Cardinal;
Obj: TXObject;
begin
SetLength(selectBuff, _XObjects.Count);

glGetIntegerv(GL_VIEWPORT, @vp);
glSelectBuffer(_XObjects.Count, @selectBuff);

glMatrixMode(GL_PROJECTION);
glPushMatrix;
glRenderMode(GL_SELECT);
_XEngine.Selection := True;

glInitNames;
glPushName(0);
glLoadIdentity;

gluPickMatrix(X, Y, 1, 1, vp);
gluPerspective(45.0, vp[2]/vp[3], 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);

_XEngine.DoRender;

hits := glRenderMode(GL_RENDER);

Obj := Nil;
If (hits > 0) Then
Begin
SelectedName := selectBuff[3];
Obj := _XO_Find(SelectedName);
End;
_XEngine.Selected := Obj;

glMatrixMode(GL_PROJECTION);
glPopMatrix;
_XEngine.Selection := False;
glMatrixMode(GL_MODELVIEW);
end;


and in the objects rendering code i have:


If Not Visible Then Exit;
If _XEngine.Selection Then glLoadName(fID);
glPushMatrix;
PreRender(Options);
DoRender(Options);
PostRender(Options);
glPopMatrix;

.. fID is a unique ID.

I have double checked it with several tutorials and examples but i cant seem to find anything i have missed :?

Can anyone see if i have missed something, or is this something with SDL/OpenGL?

vgo
27-05-2007, 11:21 AM
After rendering the objects that you want to pick load another name to the name stack with glLoadName(), like glLoadName(MaxObjectID + 1) to prevent picking the last object.

M109uk
27-05-2007, 11:50 AM
Thanks for the quick reply :)

I have added the following just after the render function:


glLoadName(_XObjects.Count+99);

yet it still selects the last face in the list :?

The selectbuff[3] has '2' assigned to it which is the id of the second face, and not of the blank one above..

vgo
27-05-2007, 12:10 PM
Here's how I process the hits in my engine:



var
SelectBuffer : array[0..512] of TGLUInt;
Viewport : TGLVectori4;
Hits,i : Integer;
HitZValue : TGLUInt;
Hit : TGLUInt;

...
Set the picking matrix etc.
Draw stuff
...

glFlush();
Hits := glRenderMode(GL_RENDER);

// Now we look which hit has the lowest Z-Value i.e. was in front
Hit := High(TGLUInt);
HitZValue := High(TGLUInt);
for i := 0 to Hits-1 do
if SelectBuffer[(i*4)+1] < HitZValue then
begin
Hit := SelectBuffer[(i*4)+3];
HitZValue := SelectBuffer[(i*4)+1];
end;


In this case Hit will be -1 if no object was at the given x/y coordinates or it will be set to the front-most object id found.

M109uk
27-05-2007, 07:47 PM
Thanks for the code :)

It didnt work at first, after a little fiddling i have managed to get it to work.. for some reason the first element in the buffer was always set at 4294965246 and resulted in only the first item being selected. however i have managed to get around this by doing:


If &#40;Hits > 0&#41; And &#40;&#40;selectBuff&#91;1&#93; <> 0&#41; Or &#40;selectBuff&#91;2&#93; <0> lZ Then
Begin
lZ &#58;= z;
hObj &#58;= selectBuff&#91;&#40;i*4&#41;+3&#93;;
End;
End;
....
End;

This seems to work fine at the moment, but only time will tell and as i test the editor and the rest of the engine i will see if it works :)

Thanks for your help

tpascal
28-05-2007, 04:49 PM
dont you should initialize "selectBuff" before using, somting like fillchar(selectbuffer[0],length(selectbuffer),0); ?

M109uk
09-06-2007, 10:42 AM
yeah you are right, im not sure why i used fillchar, but now i have it in a for loop :)