pythonopenglpyqt5vbopyopengl

PyOpenGL how to color elements by VBO


Im writing gcode sender. I want visualize path of machine work by lines (and separate G00 move lines by other color). To render element I used VBO and its works fine, but I dont know how to set individual colors for edges. I tried "mark" a vertex with G00 move in a separate list of rgb colors (as you can easy guess, its doesnt work propertly). All solutions found on the internet dont work with my code. Im really newbie in OpenGL and Im run out of ideas. 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:

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 already have

What I want:
What I want

What I get after uncomment code from OpenGl file:
What I get after uncomment code from OpenGl file


Solution

  • The last parameter of glVertexPointer and glColorPointer is not the buffer object, but an offset in to the buffer objects data store.
    When you call glVertexPointer or glColorPointer, the buffer currently bound to the target GL_ARRAY_BUFFER is associated to the fixed function attribute. You need to bind the proper buffer before calling glVertexPointer or glColorPointer:

    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)