Thread: [PyOpenGL-Users] glSelectBuffer problems
Brought to you by:
mcfletch
From: David B. <whi...@gm...> - 2007-12-14 18:14:13
|
I'm using GL_SELECT to select objects in my application, and I'm getting some strange behavior. It seems that the selection buffer is never reset, even though I am calling glRenderMode (GL_RENDER) after selection, and am calling glSelectBuffer () before each selection. Here's my code: buffer = self.view.paintGL (GL.GL_SELECT, x, y) print "Selection returned %d hits:" % (len (buffer), ) where self.view.paintGL is defined as: def paintGL (self, mode = GL.GL_RENDER, pickX = 0, pickY = 0): # Initialize the rendering deleages. self.getGeometry () if mode == GL.GL_SELECT: # Set up the selection buffer. GL.glSelectBuffer (512) GL.glRenderMode (mode) # Initialize the name stack. GL.glInitNames () GL.glPushName (0) if self.useDisplayLists: # Call the display lists to set up drawing options and # transformation matrices. GL.glCallList (self.drawOptionsListId) GL.glCallList (self.windowTransformListId) GL.glCallList (self.userTransformListId) if mode == GL.GL_SELECT: # Save the current projection matrix. GL.glMatrixMode (GL.GL_PROJECTION) prevMatrix = GL.glGetDoublev (GL.GL_PROJECTION_MATRIX) # Set up the picking matrix. viewport = GL.glGetIntegerv (GL.GL_VIEWPORT) GL.glLoadIdentity () GLU.gluPickMatrix (pickX, pickY, 3, 3, viewport) GL.glMultMatrixd (prevMatrix) # Return to MODELVIEW matrix mode. GL.glMatrixMode (GL.GL_MODELVIEW) # Clear the view to the background color. self.qglClearColor (self.colorScheme.background) GL.glClear (GL.GL_COLOR_BUFFER_BIT) try: # Render the scene. for delegate in self.delegates: delegate.render () except GL.GLerror, inst: self.log ("ERROR", str (inst)) GL.glFlush () if mode == GL.GL_SELECT: # Restore the original projection matrix. GL.glMatrixMode (GL.GL_PROJECTION) GL.glLoadMatrix (prevMatrix) if mode != GL.GL_RENDER: # Exit selection or feedback mode, and return the # selection buffer or the feedback array. return GL.glRenderMode (GL.GL_RENDER) In the above code, self.useDisplayLists is True. And here's the output from clicking on the same object repeatedly: Selection returned 32 hits: Selection returned 34 hits: Selection returned 36 hits: Selection returned 38 hits: Selection returned 40 hits: <snip> Selection returned 122 hits: Selection returned 124 hits: Selection returned 126 hits: Selection returned 128 hits: Traceback (most recent call last): File "/home/whitelynx/gne/dbz/widgets/GL3DView.py", line 525, in mouseReleaseEvent handler.click (event.x (), event.y ()) File "/home/whitelynx/gne/dbz/widgets/ButtonHandlers.py", line 9, in click buffer = self.view.paintGL (GL.GL_SELECT, x, y) File "/home/whitelynx/gne/dbz/widgets/GL3DView.py", line 213, in paintGL return GL.glRenderMode (GL.GL_RENDER) OpenGL.GL.GLerror: [Errno (1283,)] glSelectBuffer too small to hold selection results Any ideas what I'm doing wrong? -- David H. Bronke Vice President of Project Development G33X Nexus Entertainment http://www.g33xnexus.com/ v3sw5/7Hhw5/6ln4pr6Ock3ma7u7+8Lw3/7Tm3l6+7Gi2e4t4Mb7Hen5g8+9ORPa22s6MSr7p6 hackerkey.com Support Web Standards! http://www.webstandards.org/ |
From: Mike C. F. <mcf...@vr...> - 2007-12-16 17:39:03
|
David Bronke wrote: > I'm using GL_SELECT to select objects in my application, and I'm > getting some strange behavior. It seems that the selection buffer is > never reset, even though I am calling glRenderMode (GL_RENDER) after > selection, and am calling glSelectBuffer () before each selection. > Here's my code: ... > GL.glRenderMode (mode) That's the line that should reset the internal counter inside your OpenGL implementation that determines how many results should be returned: An internal index into buffer is reset to 0 whenever selection mode is entered. Each time a hit record is copied into buffer, the index is incremented to point to the cell just past the end of the block of names - that is, to the next available cell. If the hit record is larger than the number of remaining locations in buffer, as much data as can fit is copied, and the overflow flag is set. If the name stack is empty when a hit record is copied, that record consists of 0 followed by the minimum and maximum depth values. We do a little bit of custom code, but AFAICS we should not be able to influence the number of hits returned by the selection buffer (see OpenGL/GL/selection.py and OpenGL/GL/pointers.py for the actual code). That is, when you enter the mode the count should be reset. When you exit the mode it returns the internal count. The buffer remaining the same should *not* be a problem, incidentally, even if it were. We copy the reported number of records out of the buffer, and GL should be writing new records for every record it reports as having been copied in, so though there might be "garbage" at the end of the array, it should *not* affect your results or the number of them reported. > Any ideas what I'm doing wrong? It might be easiest to debug if you printed out the names of each element you are seeing in the buffer. Stop after the first few frames and check to see *how* those names are getting added. If you can disable the display-list usage (i.e. call the rendering code each time) you should be able to trace through and see each call to glPushName and glPopName. If you are not balancing those two you may be getting a run-away stack of names that are left on the stacks between runs. You could use an assert that GL_NAME_STACK_DEPTH is 0 to be sure you've done it, if you don't want to disable display lists. Good luck, Mike -- ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com |
From: David B. <whi...@gm...> - 2007-12-20 06:25:03
|
On Dec 16, 2007 12:32 PM, Mike C. Fletcher <mcf...@vr...> wrote: > David Bronke wrote: > > I'm using GL_SELECT to select objects in my application, and I'm > > getting some strange behavior. It seems that the selection buffer is > > never reset, even though I am calling glRenderMode (GL_RENDER) after > > selection, and am calling glSelectBuffer () before each selection. > > Here's my code: > ... > > GL.glRenderMode (mode) > That's the line that should reset the internal counter inside your > OpenGL implementation that determines how many results should be returned: > > An internal index into buffer is reset to 0 whenever selection mode > is entered. Each time a hit record is copied into buffer, the index > is incremented to point to the cell just past the end of the block > of names - that is, to the next available cell. If the hit record is > larger than the number of remaining locations in buffer, as much > data as can fit is copied, and the overflow flag is set. If the name > stack is empty when a hit record is copied, that record consists of > 0 followed by the minimum and maximum depth values. > > We do a little bit of custom code, but AFAICS we should not be able to > influence the number of hits returned by the selection buffer (see > OpenGL/GL/selection.py and OpenGL/GL/pointers.py for the actual code). > That is, when you enter the mode the count should be reset. When you > exit the mode it returns the internal count. > > The buffer remaining the same should *not* be a problem, incidentally, > even if it were. We copy the reported number of records out of the > buffer, and GL should be writing new records for every record it reports > as having been copied in, so though there might be "garbage" at the end > of the array, it should *not* affect your results or the number of them > reported. > > Any ideas what I'm doing wrong? > It might be easiest to debug if you printed out the names of each > element you are seeing in the buffer. Stop after the first few frames > and check to see *how* those names are getting added. If you can > disable the display-list usage (i.e. call the rendering code each time) Actually, I don't use display lists for the actual geometry at all; that's all done in immediate mode, as are the glLoadName calls. I'm not using Push/Pop, because I don't really have any nested geometry... would it be advisable to switch over to Push/Pop anyway? I was missing the closing glPopName() call in paintGL() though, so I put that back in, and realized that my way of calculating the names needed to change. I was trying to coerce the signed int object ids generated by python's id() call into unsigned ints so I could use them as names, and then get them back as valid ids... instead I just switched to an auto-increment ID for the objects, which seems to work great. I'm pretty sure the root of the problem was the lack of a glPopName() at the end of paintGL(), since effectively the name stack was simply growing without bound until it overflowed the select buffer. Thanks for the help! you should be able to trace through and see each call to glPushName and > glPopName. If you are not balancing those two you may be getting a > run-away stack of names that are left on the stacks between runs. You > could use an assert that GL_NAME_STACK_DEPTH is 0 to be sure you've done > it, if you don't want to disable display lists. > > Good luck, > Mike > > -- > ________________________________________________ > Mike C. Fletcher > Designer, VR Plumber, Coder > http://www.vrplumber.com > http://blog.vrplumber.com > > -- David H. Bronke Vice President of Project Development G33X Nexus Entertainment http://www.g33xnexus.com/ v3sw5/7Hhw5/6ln4pr6Ock3ma7u7+8Lw3/7Tm3l6+7Gi2e4t4Mb7Hen5g8+9ORPa22s6MSr7p6 hackerkey.com Support Web Standards! http://www.webstandards.org/ |