简体   繁体   English

PyOpenGL 如何通过 VBO 为元素着色

[英]PyOpenGL how to color elements by VBO

Im writing gcode sender.我在写 gcode 发件人。 I want visualize path of machine work by lines (and separate G00 move lines by other color).我想按线可视化机器工作的路径(并用其他颜色分隔 G00 移动线)。 To render element I used VBO and its works fine, but I dont know how to set individual colors for edges.为了渲染元素,我使用了 VBO 并且它工作正常,但我不知道如何为边缘设置单独的颜色。 I tried "mark" a vertex with G00 move in a separate list of rgb colors (as you can easy guess, its doesnt work propertly).我尝试在一个单独的 rgb 颜色列表中用 G00 移动“标记”一个顶点(你很容易猜到,它不能正常工作)。 All solutions found on the internet dont work with my code.在互联网上找到的所有解决方案都不适用于我的代码。 Im really newbie in OpenGL and Im run out of ideas.我真的是 OpenGL 的新手,我的想法已经用完了。 Maybe someone can show me a solution that I dont see.也许有人可以向我展示一个我看不到的解决方案。 For help I really thanks.对于帮助我真的很感谢。

My code that extracts points from the buffer and establish edges:我从缓冲区中提取点并建立边缘的代码:

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, 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]

My OpenGL code:我的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, -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, -1)).astype(np.float32))
            self.vertVBO.bind()

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

            self.edges = np.array([])

    def initializeGL(self):
        glClearColor(0.0, 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, 0, w, h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        aspect = w / float(h)

        gluPerspective(45.0, aspect, 1.0, 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, 0.0, -50.0)
        glScale(0.1, 0.1, 0.1)
        glRotate(self.rotX, 1.0, 0.0, 0.0)
        glRotate(self.rotY, 0.0, 1.0, 0.0)
        glRotate(self.rotZ, 0.0, 0.0, 1.0)
        glTranslate(-0.5, -0.5, -0.5)

        glEnableClientState(GL_VERTEX_ARRAY)
       # glEnableClientState(GL_COLOR_ARRAY)

        glVertexPointer(3, GL_FLOAT, 0, self.vertVBO)
       # glColorPointer(3, GL_FLOAT, 0, 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:我想要的是:
我想要的是

What I get after uncomment code from OpenGl file:从 OpenGl 文件中取消注释代码后我得到了什么:
从 OpenGl 文件中取消注释代码后我得到了什么

From the OpenGL Specification for glVertexPointer来自glVertexPointer的 OpenGL 规范

If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target (see glBindBuffer) while a vertex array is specified, pointer is treated as a byte offset into the buffer object's data store.如果在指定顶点数组时将非零命名缓冲区对象绑定到 GL_ARRAY_BUFFER 目标(请参阅 glBindBuffer),则将指针视为缓冲区对象数据存储中的字节偏移量。

Essentially this means that the last parameter of the glVertexPointer specifies an offset into the last bound buffer and not the actual buffer itself.本质上,这意味着glVertexPointer的最后一个参数指定了最后一个绑定缓冲区的偏移量,而不是实际缓冲区本身。

So in order to rectify this, you need to bind your vertVBO and specify the glVertexPointer and then bind the clrVBO and specify the glColorPointer .因此,为了纠正此问题,您需要绑定vertVBO并指定glVertexPointer ,然后绑定clrVBO并指定glColorPointer This lets OpenGL know that there are two buffers with separate data.这让 OpenGL 知道有两个缓冲区具有单独的数据。

Example:例子:

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

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

The last parameter of glVertexPointer and glColorPointer is not the buffer object, but an offset in to the buffer objects data store. glVertexPointerglColorPointer的最后一个参数不是缓冲区对象,而是缓冲区对象数据存储中的偏移量。
When you call glVertexPointer or glColorPointer , the buffer currently bound to the target GL_ARRAY_BUFFER is associated to the fixed function attribute.当您调用glVertexPointerglColorPointer ,当前绑定到目标GL_ARRAY_BUFFER的缓冲区与固定函数属性相关联。 You need to bind the proper buffer before calling glVertexPointer or glColorPointer :您需要在调用glVertexPointerglColorPointer之前绑定正确的缓冲区:

glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM