【问题标题】:Why does my pyglet application draw funny?为什么我的 pyglet 应用程序画得很有趣?
【发布时间】:2020-10-23 09:28:57
【问题描述】:

我用来查看 STL 格式的 3-d 对象的 pyglet 应用程序表现得很有趣。 当我加载一个 stl 文件时,它工作正常,但是当我尝试绘制它时,它的行为很有趣。 代码不会崩溃,但我为多维数据集加载的测试文件看起来不正确。我认为它可能会加入我不想加入的绘图代码中的所有点。测试文件应显示为 30 x 30 像素,而不是整个右上角:

a picture showing that a chunk of the display is the cube

在 150 度时,看起来几乎正确...

红线是线框,绿点是顶点,灰色是立方体的一个面。

这是我的代码:

print("starting Wireframe Viewer")
import pyglet, wireframe
from pyglet.gl import *

verticeColor = (0, 100, 0)
verticeSize = 4
lineColor = (100, 0, 0)
lineSize = 2
faceColor = (200, 200, 200)
menuColor = (0, 0, 100)
backgroundColor = (0, 0, 50)
gridColor = (255, 255, 255)
mode = 'OBJ'  # normal viewing - see all faces and such

pos = [0, 0, -20]
rot_y = 0
rot_x = 0
rot_z = 0

if __name__ == "__main__":
    # good
    window = pyglet.window.Window(640, 480, resizable=True)
    wf = wireframe.Wireframe()

    # good
    wf.importStl('test.stl')
    wf.dumpData()


    @window.event
    def on_draw():
        # creating 3D viewport
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(10, 1, 0.1, 100)

        glTranslatef(*pos)
        glRotatef(rot_y, 0, 1, 0)
        glRotatef(rot_x, 1, 0, 0)
        glRotatef(rot_z, 0, 0, 1)

        glClearColor(0.0, 0.0, 0.15, 0.0)
        window.clear()

        # load line width and point size
        glLineWidth(lineSize)
        glPointSize(verticeSize)
        stlDrawDat = []
        for dat in wf.stlMesh:
            stlDrawDat.append([[dat[0], dat[1], dat[2]],
                               [dat[3], dat[4], dat[5]],
                               [dat[6], dat[7], dat[8]]])
        # drawing the image
        for dat in stlDrawDat:
            pyglet.graphics.draw(3, GL_TRIANGLES,
                                 ('v3f', [*dat[0], *dat[1], *dat[2]]), ('c3B', faceColor * 3))
            pyglet.graphics.draw(3, GL_LINES,
                                 ('v3f', [*dat[0], *dat[1], *dat[2]]), ('c3B', lineColor * 3))
            pyglet.graphics.draw(3, GL_POINTS,
                                 ('v3f', [*dat[0], *dat[1], *dat[2]]), ('c3b', verticeColor * 3))

        glFlush()


    @window.event
    def on_key_press(s, m):
        # good
        global pos, rot_y, rot_x, rot_z

        if m:
            pass
        if s == pyglet.window.key.W:
            rot_x += 5  # pos[2] -= 1
        if s == pyglet.window.key.S:
            rot_x -= 5  # pos[2] += 1
        if s == pyglet.window.key.A:
            rot_y += 5
        if s == pyglet.window.key.D:
            rot_y -= 5
        if s == pyglet.window.key.Q:
            rot_z += 5
        if s == pyglet.window.key.E:
            rot_z -= 5
        if s == pyglet.window.key.MINUS:
            pos[2] -= 1
        if s == pyglet.window.key.EQUAL:
            pos[2] += 1
        if s == pyglet.window.key.LEFT:
            pos[0] -= 1
        if s == pyglet.window.key.RIGHT:
            pos[0] += 1
        if s == pyglet.window.key.UP:
            pos[1] += 1
        if s == pyglet.window.key.DOWN:
            pos[1] -= 1


    pyglet.app.run()

如果需要,我可以添加我的外部文件wireframe.py:

import numpy
from stl import mesh


class Wireframe:
    def __init__(self):
        self.stlMesh = numpy.zeros((0, 9))
        self.originalMesh = numpy.zeros((0, 9))
        self.backupMesh = numpy.zeros((0, 9))

    def importStl(self, fileName):
        print("importing ", fileName)
        self.stlMesh = mesh.Mesh.from_file(fileName)
        self.originalMesh = mesh.Mesh.from_file(fileName)
        self.backupMesh = mesh.Mesh.from_file(fileName)

    def dumpData(self):
        print('\nstl data:')
        for x in self.stlMesh:
            print(x)


if __name__ == "__main__":
    wf = Wireframe()
    wf.importStl('test.stl')
    wf.dumpData()

如果有人可以帮助我解决问题,我会很高兴。 我认为问题出在绘图功能的某个地方。如果我需要缩短我的代码,请告诉我! 在我从另一篇文章中添加 3-D 视图代码之前,它一直在工作:How do I make 3D in pyglet?

运行代码所需的模块:

python-utils
pyglet
numpy
numpy-stl

【问题讨论】:

  • “有趣”是什么意思?几何图形似乎正确渲染。可能你已经预料到了一些不同的东西,但它看起来并没有“错误”。请注意,您使用透视投影, (0, 0) 位于窗口的中心。您的视野角度非常小(10°)。增加视野角度,例如gluPerspective(90, 1, 0.1, 100)
  • 我已经试过了,我会试试gluPerspective(180, 1, 0.1, 100)谢谢!
  • 起初,我将gluPerspective() 角度设置为90
  • 150 的角度效果不错,我将发布结果图片...
  • 正面是矩形的。脸还在伸展……

标签: python python-3.x opengl pyglet opengl-compat


【解决方案1】:

gluPerspective 定义了一个Viewing frustum

在视图空间中,视图的原点是相机位置,所有具有 x 和 y 坐标 (0, 0) 的点都在视图中心的视线上。
gluPerspective 的第一个参数是沿 y 轴的视场角,以度为单位。角度必须为0° < fovAngle < 180°。因此 0° 和 180° 不是有效角度。

第二个参数是纵横比。

10° 的视场似乎远非如此。由于窗口大小为 640x480,因此纵横比必须为 640.0/480.0

gluPerspective(10, 1, 0.1, 100)

gluPerspective(120.0, 640.0/480.0, 0.1, 100)

另外我建议启用Depth Test:

glEnable(GL_DEPTH_TEST)

【讨论】:

  • 我确实看过,我一定没有注意到深度测试说明的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
  • 2012-12-27
  • 2021-04-30
  • 2017-09-22
相关资源
最近更新 更多