Hierarchical Picking in Display List

If we put a hierarchical object with several parts in one display list using GL_COMPILE(not GL_COMPILE_AND_EXECUTE), can we do Hierarchical Picking of the individual parts of the object?

Selection is only available when we do the actual rendering work, right? If we put the hierarchical object in one display list and call this list later when rendering, there is no way for us to push names of the individual parts of the object onto the name stack, right? Any solution?

there are 2 solutions:

  • store your glPushNames in the display list. if you’re not in selecting mode, these call are ignored.
  • create 2 lists, one for rendering and one for selecting.

I think that the second method is the best. selection don’t need texturing or lighting to work. so in the second list, you just have to send the geometry to the gpu and it is faster.
the only problem is that implies to create two lists and if the object is quite big, it could burn a lot of memory.

Thanks!

How can I store glPushNames in the display list? Call glPushNames when I generate a new list?

I tried that. It looks that solution 2 does not work. To my understanding, hit records are only generated when rendering. Although programs call glCallList in rendering, it won’t call glPushNames hided in the display list. Let me know if my understanding is wrong. Thanks!

it should work.
take care how you create the second display list (the one with glPushName calls). you can’t call glRenderMode() in a list.

you have to do:
uint create_select_list()
{
uint id = glGenList(1);
glNewList(id, GL_COMPILE);
render the scene without normals, texture coordinates and with glPushName and glLoadName calls.
glEndList();
return id;
}

and when you want to select an object:
void select()
{
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glRenderMode(GL_SELECT);
glCallList(select_list);
n = glRenderMode(GL_RENDER);
process_hits();
}

do you do something like that ?

Thanks for your reply. When I said solution 2 did not work, I made a mistake. My actual meaning was that solution 1 did not work. I prefer solution 1 if it works because my list of drawing objects is big. Any suggestion on solution one?

[This message has been edited by Rong Yao (edited 07-23-2003).]

try to insert some glGetError to see if something goes wrong.
in a list those function call are not allowed:
glDeleteLists(), glIsEnabled(), glFeedbackBuffer(), glIsList(),
glFinish(), glPixelStore(),
glFlush(), glReadPixels(),
glGenLists(), glRenderMode(),
glGet*(), glSelectBuffer().

I do not have any function you mentioned between glNewList and glEndList. To my understanding, at the time of rendering, glCallList ignores glPushName we put before glNewList when we create the display list.
Am I wrong?

check the value returned by glGetError() after a glPushName() or a glLoadName(). it should be 0.

the gl*Name calls are not allowed between a glBegin and a glEnd.

the gl*Name calls are ignored when the render mode is not GL_SELECT. maybe the driver discard them before doing display list operations.

it sound strange. since the gl*name calls are allowed between a glNewList and en glEndList, those calls must be registered as glVertex calls.

Hit record is not zero now. It did not work before probably because I did not change matrix mode back to GL_MODELVIEW when rendering started.

However, glGetError() returns 1280 instead of 0, it should be GL_INVALID_ENUM. But I do have an unacceptable value which is specified for an enumerated argument?
[This message has been edited by Rong Yao (edited 07-24-2003).]

[This message has been edited by Rong Yao (edited 07-24-2003).]

what function cause this error ?
glPushName and glLoadName can only throw GL_STACK_OVERFLOW, GL_STACK_UNDERFLOW or GL_INVALID_OPERATION (according to man pages).

does the hit count is right ?

Hit count looks right. Probably the error is caused by other code.