Normally in OpenGL to use a selection buffer one would do the following:
GLuint buffer[SIZE]; glSelectBuffer(SIZE, buffer); glRenderMode(GL_SELECT); /* draw some stuff */ GLint count = glRenderMode(GL_RENDER); /* parse the selection buffer */
In Python this accomplished like this:
glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements glRenderMode(GL_SELECT) # draw some stuff buffer = glRenderMode(GL_RENDER) for hit_record in buffer: min_depth, max_depth, names = hit_record # do something with the record
Feedback buffers are used in the same way except that each item in the buffer is tuple (token, value), where value is either a passthrough token or a list of vertices. Note that if glRenderMode returns a buffer than it also resets OpenGL's pointer for the corresponding buffer. This means that the buffer returned by glRenderMode is independent of future calls to glRenderMode, i.e. it will not be overwritten by any such future calls. This makes the returned buffer somewhat thread-safe. It also means that every call to glRenderMode(GL_SELECT | GL_FEEDBACK) needs to preceded by a call to glSelectBuffer or glFeedbackBuffer first, i.e. the following code will not work
glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements glRenderMode(GL_SELECT) # draw some stuff buffer = glRenderMode(GL_RENDER) # do another selection glRenderMode(GL_SELECT) # draw some stuff buffer = glRenderMode(GL_RENDER)
Instead one must
glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements glRenderMode(GL_SELECT) # draw some stuff buffer = glRenderMode(GL_RENDER) # do another selection glSelectBuffer(SIZE) allocate a new selection buffer glRenderMode(GL_SELECT) # draw some stuff buffer = glRenderMode(GL_RENDER)
In previous versions of PyOpenGL in order to perform selection one would use the glSelectWithCallback function. This function is still available, but the only thing that it does in addition to the method described above is setup the projection matrix using gluPickMatrix.
Each call which sets an array pointer, such as glVertexPointer, will have many variants. First there will a function which is identical that of the specification. For the pointer argument one should pass a string. Also note that the stride values are used.
Next there will a set of functions named
glXPointer{ub|b|us|s|ui|i|f|d}
These will usually take as a single argument a multidimensional array of values. The type argument is controlled by the suffix of the function (ub is unsigned byte, etc.) All other arguments are derived from the dimensions of the array.
So for glColorPointer we have:
glColorPointer(size, type, stride, pointer) -> None glColorPointerub(pointer[][]) -> None glColorPointerb(pointer[][]) -> None glColorPointerus(pointer[][]) -> None glColorPointers(pointer[][]) -> None glColorPointerui(pointer[][]) -> None glColorPointeri(pointer[][]) -> None glColorPointerf(pointer[][]) -> None glColorPointerd(pointer[][]) -> None
This same decoration strategy is used for other array functions besides glXPointer. For instance, glDrawElements has the Python binding:
glDrawElements(mode, count, type, indices) -> None
where indices is expected to be a string. There are also the decorated bindings
glDrawElementsub(mode, indices[]) -> None glDrawElementsus(mode, indices[]) -> None glDrawElementsui(mode, indices[]) -> None
where "indices" is now a single dimensional array.
When calling a glColorPointer, glVertexPointer, etc. Python needs to allocate memory to store the values that OpenGL needs. This memory is reference counted and takes into account function calls like glPushClientAttrib and glPopClientAttrib. To force this memory to be released one just need to make a call glColorPointerub(None).
Currently glPushClientAttrib will always set the GL_CLIENT_VERTEX_ARRAY_BIT flag as glPopClientAttrib has no way of knowing that flag was set and the state of the flag is needed to know whether or not to decrement the pointer locks on the allocated memory. This may change in the future. That said, surrounding array use glPushClientAttrib/glPopClientAttrib is a good way to force the release of any allocated memory, but make sure that all calls to glXPointer, etc. are within the ClientAttrib block if you chose to use this scheme.
Since all the memory allocation is automatic there is no need for glGetPointerv function, so it is excluded.
glDrawPixels and the other image/texturing functions have much the same decoration scheme as the array functions. For glDrawPixels there is the standard function which expects a string as the pixel data:
glDrawPixels(width, height, format, type, pixels) -> None
This function will respect the parameters set by glPixelStore{i|f}. There is also a collection of variants which take a multidimensional array as the data source and set glPixelStore{i|f} automatically. For example:
glDrawPixelsub(format, pixels) -> None
Notice that width and height are inferred from the pixel data and the type is GLubyte.
In OpenGL the current error status is retrieved with the function glGetError. This function returns an error code and clears the current error status at the same time. On some distributed systems multiple errors may be generated at a time. In that case it is necessary to call glGetError multiple times.
PyOpenGL does not expose the glGetError. Instead it automatically checks the error status and throws an instance of GL.GLerror on an error. This is a more "Pythonic" approach. GL.GLerror is a subclass of EnvironmentError and has a errno and msg like EnvironmentError. In the case of multiple errors the errno attribute will be set to a tuple of error numbers and msg will be a concatenation of the error messages for each error.