0

I have a project when I need to do boolean operations with 3D models (CGS mainly), and I was trying to implement the example given on the library for python but it is not working. Seems like the code runs on OpenGL and the error comes from it instead of the example.

Anybody has an idea of how to make it work? What am I missing?

Here is the error I get and the library link is below.

OpenGL.error.NullFunctionError: Attempt to call an undefined function glutInit, check for bool(glutInit) before calling

Library link: https://github.com/timknip/pycsg

Example code

import sys
import os

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *

sys.path.insert(0, os.getcwd())

from csg.core import CSG
from csg.geom import Vertex, Vector

from optparse import OptionParser

light_ambient = [0.3, 0.3, 0.3, 1.0]
light_diffuse = [0.7, 0.7, 0.7, 1.0]  # Red diffuse light
light_position = [100.0, 100.0, 100.0, 0.0]  # Infinite light location.

rot = 0.0

class TestRenderable(object):
    def __init__(self, operation):
        self.faces = []
        self.normals = []
        self.vertices = []
        self.colors = []
        self.vnormals = []
        self.list = -1

        a = CSG.cube()
        b = CSG.cylinder(radius=0.5, start=[0., -2., 0.], end=[0., 2., 0.])
        for p in a.polygons:
            p.shared = [1.0, 0.0, 0.0, 1.0]
        for p in b.polygons:
            p.shared = [0.0, 1.0, 0.0, 1.0]

        recursionlimit = sys.getrecursionlimit()
        sys.setrecursionlimit(10000)
        try:
            if operation == 'subtract':
                polygons = a.subtract(b).toPolygons()
            elif operation == 'union':
                polygons = a.union(b).toPolygons()
            elif operation == 'intersect':
                polygons = a.intersect(b).toPolygons()
            else:
                raise Exception('Unknown operation: \'%s\'' % operation)
        except RuntimeError as e:
            raise RuntimeError(e)
        sys.setrecursionlimit(recursionlimit)

        for polygon in polygons:
            n = polygon.plane.normal
            indices = []
            for v in polygon.vertices:
                pos = [v.pos.x, v.pos.y, v.pos.z]
                if not pos in self.vertices:
                    self.vertices.append(pos)
                    self.vnormals.append([])
                index = self.vertices.index(pos)
                indices.append(index)
                self.vnormals[index].append(v.normal)
            self.faces.append(indices)
            self.normals.append([n.x, n.y, n.z])
            self.colors.append(polygon.shared)

        # setup vertex-normals
        ns = []
        for vns in self.vnormals:
            n = Vector(0.0, 0.0, 0.0)
            for vn in vns:
                n = n.plus(vn)
            n = n.dividedBy(len(vns))
            ns.append([a for a in n])
        self.vnormals = ns

    def render(self):
        if self.list < 0:
            self.list = glGenLists(1)
            glNewList(self.list, GL_COMPILE)

            for n, f in enumerate(self.faces):
                glMaterialfv(GL_FRONT, GL_DIFFUSE, self.colors[n])
                glMaterialfv(GL_FRONT, GL_SPECULAR, self.colors[n])
                glMaterialf(GL_FRONT, GL_SHININESS, 50.0)
                glColor4fv(self.colors[n])

                glBegin(GL_POLYGON)
                if self.colors[n][0] > 0:
                    glNormal3fv(self.normals[n])

                for i in f:
                    if self.colors[n][1] > 0:
                        glNormal3fv(self.vnormals[i])
                    glVertex3fv(self.vertices[i])
                glEnd()
            glEndList()
        glCallList(self.list)

renderable = None

def init():
    # Enable a single OpenGL light.
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
    glLightfv(GL_LIGHT0, GL_POSITION, light_position)
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);

    # Use depth buffering for hidden surface elimination.
    glEnable(GL_DEPTH_TEST);

    # Setup the view of the cube.
    glMatrixMode(GL_PROJECTION);
    gluPerspective(40.0, 640./480., 1.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.)

def display():
    global rot
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glPushMatrix()
    glTranslatef(0.0, 0.0, -1.0);
    glRotatef(rot, 1.0, 0.0, 0.0);
    glRotatef(rot, 0.0, 0.0, 1.0);
    rot += 0.1

    renderable.render()

    glPopMatrix()
    glFlush()
    glutSwapBuffers()
    glutPostRedisplay()

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option('-o', '--operation', dest='operation',
                      type='str', default='subtract')
    (options, args) = parser.parse_args()

    renderable = TestRenderable(options.operation)

    glutInit()
    glutInitWindowSize(640,480)
    glutCreateWindow("CSG Test")
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
    glutDisplayFunc(display)

    init()

    glutMainLoop()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174

1 Answers1

0

There is a issue when installing pyopengl with pip install pyopengl on Windows systems.

Go to Unofficial Windows Binaries for Python Extension Packages

Download a 32 bit or 64 bit package for PyOpenGL provides bindings to OpenGL, GLUT, and GLE
(e.g.
PyOpenGL‑3.1.5‑cp39‑cp39‑win_amd64.whl and
PyOpenGL_accelerate‑3.1.5‑cp39‑cp39‑win_amd64.whl)

Open Command Prompt (cmd.exe) as administrator. Change to the download directory and install the packages by pip install packagename.whl.

e.g:

pip install PyOpenGL‑3.1.5‑cp39‑cp39‑win_amd64.whl

and

pip install PyOpenGL_accelerate‑3.1.5‑cp39‑cp39‑win_amd64.whl

If the package is already installed, but doesn't work, then you have to ignore the currently installed package, by the option --ignore-installed:

pip install --ignore-installed PyOpenGL‑3.1.5‑cp39‑cp39‑win_amd64.whl
pip install --ignore-installed PyOpenGL_accelerate‑3.1.5‑cp39‑cp39‑win_amd64.whl
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • I already tried installing different wheels and nothing works. I even tried running the code only with PyOpenGL without the accelerate and it doesnt work. – EmanuelMtzV Feb 09 '21 at 18:16
  • @EmanuelMtzV I had the same problem. I searched for a long time and finally found this solution. It worked for me and seems like the only solution. So you did something wrong. – Rabbid76 Feb 09 '21 at 18:17
  • Just to finish this question. You were right, PyOpenGL was installed incorrectly. Yet, my issue to install the wheels from https://www.lfd.uci.edu/~gohlke/pythonlibs/ was that my python wheel program as not updated. So, I had to update my wheel following this link: https://packaging.python.org/tutorials/installing-packages/ Once my wheel and PyOpenGL was updated, I can run the example. Thanks! – EmanuelMtzV Feb 12 '21 at 01:53