Menu

#28 "Invalid enumerant" when rendering a bezier curve (Win32)

Bug
closed
nobody
None
5
2010-04-01
2010-03-22
Alex
No

I'm trying to display a simple scene with a bezier curve (see attached file).

Under Linux (Ubuntu Karmic, Python 2.6, cgkit 2.0.0alpha9, PyOpenGL 3.0.0), the scene renders very well. Under Windows XP, I get this traceback:

C:\Python26\Scripts>c:\python26\python viewer.py z:\bezier.py
Traceback (most recent call last):
File "viewer.py", line 667, in <module>
viewer.run()
File "c:\python26\lib\site-packages\cgkit\tool.py", line 198, in run
self.action()
File "viewer.py", line 377, in action
self.draw(self.cam, width, height)
File "viewer.py", line 644, in draw
renderer.paint(root)
File "c:\python26\lib\site-packages\cgkit\beziercurvegeom.py", line 201, in drawGL
glPushAttrib(GL_LIGHTING_BIT)
File "C:\Python26\Lib\site-packages\OpenGL\error.py", line 208, in glCheckError
baseOperation = baseOperation,
OpenGL.error.GLError: GLError(
err = 1280,
description = 'invalid enumerant',
baseOperation = glPushAttrib,
cArguments = (GL_LIGHTING_BIT,)
)

I have tried cgkit 2.0.0alpha9 with Python 2.5 and 2.6, PyOpenGL 3.0.0, 3.0.1 and development version (bzr), with no success. The renderer is software (Windows XP under VirtualBox). Other scripts which use PyOpenGL run correctly. Other cgkit scenes, with complex trimeshes and lighting, work flawlessly.

The problem seems to be mixing OpenGL calls from Python and C++ support library.

I am also trying to compile cgkit from git to see if the problem persists.

Discussion

  • Alex

    Alex - 2010-03-22

    Scene file on which I get the error

     
  • Alex

    Alex - 2010-03-22

    I have compiled cgkit from git (today's snapshot) with MSVC 2003, Python 2.5, Boost 1.42.0, Win XP. Before compiling, I have uninstalled and deleted other versions of Python and cgkit. All the demos from cgkit run correctly; however, the BezierCurve fails to render, with the same traceback.

     
  • Matthias Baas

    Matthias Baas - 2010-03-22

    I don't get that error here running WinXP (natively, not in VirtualBox) and using PyOpenGL 3.0.0.
    It fails on the line glPushAttrib(GL_LIGHTING_BIT) which is nothing special as far as I can tell, so I would assume this should even work with old versions of OpenGL. So you are saying you can run other OpenGL programs just fine?
    It does look like an OpenGL problem to me. Can you run the following in a Python shell:

    >>> from OpenGL.GL import *
    >>> int(GL_LIGHTING_BIT)
    64

    Do you also get 64? Can you locate your C header file gl.h and check the value of the constant in there? (the values should match)
    Maybe it would also be worth setting up a little Python OpenGL program that just runs this glPushAttrib() call and see what happens there (as I don't think the error has anything to do with cgkit).
    I also wouldn't expect any problems with mixing C++ and Python OpenGL commands. As long as the same OpenGL context is active this should just be fine (eventually the Python calls will also end up doing the corresponding C calls, so it's really the same).

     
  • Nobody/Anonymous

    I can successfully run the GL_LIGHTING_BIT script in the python shell, so the problem is not there. Then I have run a few more tests:

    1) I tried to call glColor3f(0,0,0) in the main loop of viewer.py, like this:
    ...
    self.draw(self.cam, width, height)
    glColor3f(0,0,0)
    ...
    Result: glColor3f fails with invalid enumerant.

    2) I tried to isolate the problem. If I comment out "renderer.paint(root)" in viewer.py,
    then glColor3f works OK (and also other OpenGL calls).

    3) I have recompiled cgkit with MSVC2003, and commented the following lines from glrender.cpp:

    /*
    if (separate_specular_color)
    glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
    else
    glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
    */

    After commenting them, Bezier curve rendered perfectly. So for now, the problem is fixed for me, but maybe other people have this problem as well. I have tested on two more XP computers (one native and the other via Remote Desktop) and none of them worked with the cgkit release.

    My conclusion (it may be wrong): after calling glLightModeli in glrender.cpp, almost any OpenGL call from Python fails with "invalid enumerant". But the calls from glrender.cpp still work correctly.

    If the program works on your machine out of the box, it may be a video driver issue.

    Otherwise, the library works great, keep up the good work!

     
  • Matthias Baas

    Matthias Baas - 2010-03-24
    • status: open --> open-fixed
     
  • Matthias Baas

    Matthias Baas - 2010-03-24

    Ah, ok, good catch! I can see now what's going on. In your case, the C++ code triggers the OpenGL error flag (I'm quite convinced you are running an OpenGL version <1.2. The GL_LIGHT_MODEL_COLOR_CONTROL parameter is only available as of OpenGL 1.2 and trying to set this on older versions will result in the above "invalid enum" error), but the C++ code never sets the error flag back, so when control goes back to Python and you do an arbitrary Python call, the wrappers will see that the error flag is set and produce an exception (I'm actually not sure if raising exceptions in this particular case is such a good thing).
    I have just pushed a fix for this, the C++ code will now always reset the error flag at the end. Can you grab the source code from the git repository and see if it fixes the issue?

    Could you also confirm that you are really running OpenGL <1.2? For example, you could run the viewer tool with the -v option. This will print the OpenGL version.

    - Matthias -

     
  • Alex

    Alex - 2010-03-25

    Thank you very much for fixing!

    You were right, I was running OpenGL 1.1. Also, thanks for the tip about retrieving OpenGL info!

    OpenGL information:
    Vendor : Microsoft Corporation
    Renderer: GDI Generic
    Version : 1.1.0

    On Linux I had OpenGL 2.1 (Mesa), so that's why it worked.

    Now I will try to get the code from git and see if it compiles.

     
  • Alex

    Alex - 2010-03-27

    I'm sorry to say that the latest version from git did not fix the issue. I have changed the for loop in glrender.cpp to:

    for(int i=0; i<10; i++)
    {
    printf("glGetError() => %d\n", glGetError());
    if (glGetError()==GL_NO_ERROR)
    break;
    }

    Result: the error appears BEFORE reaching the for loop.

    I think some Python rendering code is called in drawScene(...).

    Therefore, I added another for loop for clearing gl errors, immediately after
    glLightModeli.

    Result:

    C:\Python25\Scripts>python viewer.py z:\bezier.py
    dInitODE()
    GLRenderInstance::paint(WorldObject& root)
    glGetError() immediately after glLightModeli => 1280
    glGetError() => 0
    GLRenderInstance::paint(WorldObject& root)
    glGetError() immediately after glLightModeli => 1280
    ... etc ...

    Problem fixed.

    Now, I'm not sure where it is better to place the for loop for clearing the GL error.
    If I leave it immediately after glLightModeli, it works for me, but will not catch other GL errors. Should it be right before geom->DrawGL (glrender.cpp:390) ?
    Is there any other place where the renderer is calling other OpenGL functions from Python?

    I have added a patch which fixes the problem for me here:
    https://sourceforge.net/tracker/?func=detail&aid=2977445&group_id=50475&atid=459849

     
  • Alex

    Alex - 2010-03-27
    • status: open-fixed --> open
     
  • Alex

    Alex - 2010-04-01
    • status: open --> closed
     

Log in to post a comment.