PyOpenGL how to color elements by VBO

Viewed 149

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

2 Answers

From the OpenGL Specification for glVertexPointer

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.

Essentially this means that the last parameter of the glVertexPointer specifies an offset into the last bound buffer and not the actual buffer itself.

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. This lets OpenGL know that there are two buffers with separate data.

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.
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)
Related