微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PyOpenGL 如何通过 VBO 为元素着色

如何解决PyOpenGL 如何通过 VBO 为元素着色

我正在编写 gcode 发送器。我想按线可视化机器工作的路径(并用其他颜色分隔 G00 移动线)。为了渲染元素,我使用了 VBO 并且它工作正常,但我不知道如何为边缘设置单独的颜色。我尝试在一个单独的 rgb 颜色列表中用 G00 移动“标记一个顶点(你很容易猜到,它不能正常工作)。在互联网上找到的所有解决方案都不适用于我的代码。我真的是 OpenGL 的新手,我的想法已经用完了。也许有人可以向我展示一个我看不到的解决方案。非常感谢您的帮助。

我从缓冲区中提取点并建立边的代码

def get_edges(self):
    for x in range(0,len(self.points) - 2):
        self.edges.append(x)
        self.edges.append(x+1)
        self.edges.append(x+1)
        self.edges.append(x)

def get_points_from_buffer(self):
    is_first_zminmax = True
    is_first_fminmax = True
    last_motion_mode = None

    for command in self.buffer:

        if command.find("G") != -1:
            last_motion_mode = command[command.find("G"):command.find("G") + 3]

        if command.find("F") != -1:
            start = command.find("F") + 1
            stop = start
            while command[stop].isalpha() is False and stop < len(command) - 1 and command[stop] != ";":
                stop += 1
            if start == stop:
                f = int(command[start])
            else:
                if stop == len(command) - 1:
                    f = int(command[start:stop+1])
                else:
                    f = int(command[start:stop])

            if is_first_fminmax is True:
                is_first_fminmax = False
                self.FMinMax[0] = f
                self.FMinMax[1] = f
            elif f < self.FMinMax[0]:
                self.FMinMax[0] = f
            elif f > self.FMinMax[1]:
                self.FMinMax[1] = f

        if command.find("X") != -1 or command.find("Y") != -1 or command.find("Z") != -1:
            if last_motion_mode == "G00":
                self.colors.append((0.25,1.0,0.0))
            elif last_motion_mode != "G00":
                self.colors.append((1.0,1.0))

            if command.find("X") != -1:
                start = command.find("X") + 1
                stop = start
                while command[stop].isalpha() is False and stop < len(command) - 1 and command[stop] != ";":
                    stop += 1
                if start == stop:
                    x = float(command[start])
                else:
                    if stop == len(command) - 1:
                        x = float(command[start:stop + 1])
                    else:
                        x = float(command[start:stop])
            elif len(self.points) == 0:
                x = 0
            else:
                x = self.points[len(self.points) - 1][0]

            if command.find("Y") != -1:
                start = command.find("Y") + 1
                stop = start
                while command[stop].isalpha() is False and stop < len(command) - 1 and command[stop] != ";":
                    stop += 1
                if start == stop:
                    y = float(command[start])
                else:
                    if stop == len(command) - 1:
                        y = float(command[start:stop + 1])
                    else:
                        y = float(command[start:stop])
            elif len(self.points) == 0:
                y = 0
            else:
                y = self.points[len(self.points) - 1][1]

            if command.find("Z") != -1:
                z = self.get_z(command)

                if last_motion_mode != "G00" and is_first_zminmax is True:
                    is_first_zminmax = False
                    self.ZMinMax[0] = z
                    self.ZMinMax[1] = z
                elif last_motion_mode != "G00":
                    if z < self.ZMinMax[0]:
                        self.ZMinMax[0] = z
                    elif z > self.ZMinMax[1]:
                        self.ZMinMax[1] = z

            elif len(self.points) == 0:
                z = 0
            else:
                z = self.points[len(self.points) - 1][2]

            p = (x,y,z)
            self.points.append(p)
            self.is_motion_line.append(True)
        else:
            self.is_motion_line.append(False)

    self.difZ = self.ZMinMax[1] - self.ZMinMax[0]

我的 OpenGL 代码

from OpenGL.GL import *
from OpenGL.glu import *
from OpenGL.arrays import vbo
import numpy as np
from PyQt5 import QtOpenGL


class MyOpenGlWidget(QtOpenGL.QGLWidget):
    def __init__(self,parent=None):
        QtOpenGL.QGLWidget.__init__(self,parent)

    def initGeometry(self,points=None,edges=None,colors=None):
        if points is not None and edges is not None and colors is not None:
            self.points = np.array(points)
            self.vertVBO = vbo.VBO(np.reshape(self.points,(1,-1)).astype(np.float32))
            self.vertVBO.bind()

           # self.colors = np.array(colors)
           # self.clrVBO = vbo.VBO(np.reshape(self.colors,-1)).astype(np.float32))
           # self.clrVBO.bind()

            self.edges = np.array(edges)
        else:
            self.points = np.array([])
            self.vertVBO = vbo.VBO(np.reshape(self.points,-1)).astype(np.float32))
            self.vertVBO.bind()

            self.colors = np.array([])
            self.clrVBO = vbo.VBO(np.reshape(self.colors,-1)).astype(np.float32))
            self.clrVBO.bind()

            self.edges = np.array([])

    def initializeGL(self):
        glClearColor(0.0,0.0,0.0)
        glEnable(GL_DEPTH_TEST)

        self.initGeometry()

        self.rotX = 0.0
        self.rotY = 0.0
        self.rotZ = 0.0

    def resizeGL(self,w,h):
        glViewport(0,h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        aspect = w / float(h)

        gluPerspective(45.0,aspect,100.0)

        glMatrixMode(GL_MODELVIEW)
        glpolygonMode(GL_FRONT_AND_BACK,GL_LINE)

    def paintGL(self,coordinates=None):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glPushmatrix()

        glTranslate(0.0,-50.0)
        glScale(0.1,0.1,0.1)
        glrotate(self.rotX,0.0)
        glrotate(self.rotY,0.0)
        glrotate(self.rotZ,1.0)
        glTranslate(-0.5,-0.5,-0.5)

        glEnableClientState(GL_VERTEX_ARRAY)
       # glEnableClientState(GL_COLOR_ARRAY)

        glVertexPointer(3,GL_FLOAT,self.vertVBO)
       # glColorPointer(3,self.clrVBO)

        glDrawElements(GL_QUADS,len(self.edges),GL_UNSIGNED_INT,self.edges)

        gldisableClientState(GL_VERTEX_ARRAY)
       # gldisableClientState(GL_COLOR_ARRAY)

        glPopMatrix()

我已经拥有的:

What I already have

我想要的:

What I want

从 OpenGl 文件中取消注释代码后得到的结果:

What I get after uncomment code from OpenGl file

解决方法

来自 glVertexPointer 的 OpenGL 规范

如果在指定顶点数组时将非零命名缓冲区对象绑定到 GL_ARRAY_BUFFER 目标(请参阅 glBindBuffer),则指针将被视为缓冲区对象数据存储中的字节偏移量。

本质上这意味着 glVertexPointer 的最后一个参数指定了最后一个绑定缓冲区的偏移量,而不是实际缓冲区本身。

因此,为了解决这个问题,您需要绑定 vertVBO 并指定 glVertexPointer,然后绑定 clrVBO 并指定 glColorPointer。这让 OpenGL 知道有两个缓冲区具有不同的数据。

示例:

self.vertVBO.bind()
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3,G_FLOAT,None)

self.clrVBO.bind()
glEnableClientState(GL_COLOR_ARRAY)
glColorPointer(3,GL_FLOAT,None)
,

glVertexPointerglColorPointer 的最后一个参数不是缓冲区对象,而是缓冲区对象数据存储中的偏移量。
当您调用 glVertexPointerglColorPointer 时,当前绑定到目标 GL_ARRAY_BUFFER 的缓冲区与固定函数属性相关联。您需要在调用 glVertexPointerglColorPointer 之前绑定正确的缓冲区:

glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)

self.vertVBO.bind()
glVertexPointer(3,None)

self.clrVBO.bind()
glColorPointer(3,None)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。