首页 > 解决方案 > 用于 python 的 Cython-CSG // 示例不起作用

问题描述

当我需要对 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()

标签: pythonpyopengl

解决方案


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

转到Python 扩展包的非官方 Windows 二进制文件

为 PyOpenGL下载一个 32 位或 64 位包,提供与 OpenGL、GLUT 和 GLE 的绑定
(例如
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

推荐阅读