【问题标题】:Cython-CSG for python // Example not working [duplicate]python的Cython-CSG //示例不起作用[重复]
【发布时间】:2025-12-09 15:10:01
【问题描述】:

当我需要对 3D 模型(主要是 CGS)进行布尔运算时,我有一个项目,我试图实现 python 库中给出的示例,但它不起作用。似乎代码在 OpenGL 上运行,错误来自它而不是示例。

有人知道如何让它工作吗? 我错过了什么?

这是我得到的错误,下面是库链接。

OpenGL.error.NullFunctionError:尝试调用未定义的函数 glutInit,调用前检查 bool(glutInit)

库链接:https://github.com/timknip/pycsg

示例代码

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()

【问题讨论】:

    标签: python pyopengl


    【解决方案1】:

    在 Windows 系统上使用pip install pyopengl 安装 pyopengl 时出现问题。

    转到Unofficial Windows Binaries for Python Extension Packages

    下载PyOpenGL provides bindings to OpenGL, GLUT, and GLE的32位或64位包
    (例如
    PyOpenGL‑3.1.5‑cp39‑cp39‑win_amd64.whl
    PyOpenGL_accelerate‑3.1.5‑cp39‑cp39‑win_amd64.whl

    以管理员身份打开命令提示符 (cmd.exe)。切换到下载目录,通过pip install packagename.whl安装包。

    例如:

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

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

    如果软件包已经安装,但不能工作,那么你必须忽略当前安装的软件包,通过选项--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
    

    【讨论】:

    • 我已经尝试安装不同的*,但没有任何效果。我什至尝试只使用 PyOpenGL 运行代码而没有加速,但它不起作用。
    • @EmanuelMtzV 我遇到了同样的问题。找了半天,终于找到了这个解决方案。它对我有用,似乎是唯一的解决方案。所以你做错了什么。
    • 只是为了完成这个问题。你是对的,PyOpenGL 安装不正确。然而,我从lfd.uci.edu/~gohlke/pythonlibs 安装*的问题是我的 python *程序没有更新。所以,我必须按照这个链接更新我的*:packaging.python.org/tutorials/installing-packages 一旦我的*和 PyOpenGL 被更新,我就可以运行这个例子了。谢谢!