Search code examples
pythonopenglpygamepyopenglopengl-compat

GL_LINES not showing up on top of cube?


I am trying to create a 3d Rubiks Cube with OpenGL and Pygame. However I when I try to draw lines on top of the GL_QUADS surfaces I have created, they don't show up.

I have tried putting the GL_LINES after the GL_QUADS line but it they still do not show up as black lines.

Does anyone have a solution? Also, how would I adjust the thickness of the lines?

This is what the code looks like:

def draw(self):
    glEnable(GL_DEPTH_TEST)

    glBegin(GL_LINES)
    glColor3fv((0, 0, 0))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))

    glColor3fv((0, 0, 0))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z + self.len))
    glVertex3fv((self.x + self.len, self.y - self.len, self.z - self.len))

    glColor3fv((0, 0, 0))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))

    glColor3fv((0, 0, 0))
    glVertex3fv((self.x - self.len, self.y - self.len, self.z + self.len))
    glVertex3fv((self.x - self.len, self.y - self.len, self.z - self.len))
    glEnd()

    glBegin(GL_QUADS)

    glColor3fv(colors[0])
    # fix z
    glVertex3fv((self.x - self.len, self.y - self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y - self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))

    glColor3fv(colors[1])
    glVertex3fv((self.x - self.len, self.y - self.len, self.z + self.len))
    glVertex3fv((self.x + self.len, self.y - self.len, self.z + self.len))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z + self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z + self.len))

    # fix x
    glColor3fv(colors[2])
    glVertex3fv((self.x - self.len, self.y - self.len, self.z - self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z + self.len))
    glVertex3fv((self.x - self.len, self.y - self.len, self.z + self.len))

    glColor3fv(colors[3])
    glVertex3fv((self.x + self.len, self.y - self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z + self.len))
    glVertex3fv((self.x + self.len, self.y - self.len, self.z + self.len))

    # fix y
    glColor3fv(colors[4])
    glVertex3fv((self.x - self.len, self.y - self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y - self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y - self.len, self.z + self.len))
    glVertex3fv((self.x - self.len, self.y - self.len, self.z + self.len))

    glColor3fv(colors[5])
    glVertex3fv((self.x - self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z - self.len))
    glVertex3fv((self.x + self.len, self.y + self.len, self.z + self.len))
    glVertex3fv((self.x - self.len, self.y + self.len, self.z + self.len))

    glEnd()

Solution

  • The lines are covered by the polygons. Note, the lines and the polygons mathematically have the same depth, but in fact this is depending on floating-point arithmetic precision either the fragment which is drawn by the polygon or by the line "wins" the depth test. This may also cause Z-fighting.

    Slightly push the polygons back, by setting a depth offset (see glPolygonOffset), so the lines will be in front of the polygons:

     def draw(self):
            glEnable(GL_DEPTH_TEST) 
    
            glBegin(GL_LINES)
            # [...]
            glEnd()
    
            glEnable( GL_POLYGON_OFFSET_FILL )
            glPolygonOffset( 1.0, 1.0 )
    
            glBegin(GL_QUADS)
            # [...]
            glEnd()
    
            glDisable( GL_POLYGON_OFFSET_FILL )
    

    If you still cant see the line, then you've to increase the polygon offset (1st parameter). Note the lines are thin and drawn in black (glColor3fv((0, 0, 0))), possibly they are hardly to see.


    The thickness of a line can be set by glLineWidth


    Note, a cube consists of 8 vertices, 6 sides and 12 edges. In your code you draw only 4 edges.
    I recommend to define a list of the 8 corner points of the cube and to define a list of the 6 side quad indices and the 12 edges. Use this lists to draw the cube:

    repl.it/@Rabbid76/PyGame-opengl-cube-wireframe

    class Cube:
      
      def __init__(self, x, y, z, len):
         self.x = x
         self.y = y
         self.z = z
         self.len = len
    
         self.v = [
           (self.x - self.len, self.y - self.len, self.z - self.len),
           (self.x + self.len, self.y - self.len, self.z - self.len),
           (self.x + self.len, self.y + self.len, self.z - self.len),
           (self.x - self.len, self.y + self.len, self.z - self.len),
           (self.x - self.len, self.y - self.len, self.z + self.len),
           (self.x + self.len, self.y - self.len, self.z + self.len),
           (self.x + self.len, self.y + self.len, self.z + self.len),
           (self.x - self.len, self.y + self.len, self.z + self.len),
         ]
         self.edges = [(0,1), (1,2), (2,3), (3,0), (4,5), (5,6),
                       (6,7), (7,4), (0,4), (1,5), (2,6), (3,7)]
         self.surfaces = [(0,1,2,3), (5,4,7,6), (4,0,3,7),(1,5,6,2), (4,5,1,0), (3,2,6,7)]
    
         self.colors = [(1,0,0), (0,1,0), (0,0,1), (1,1,0), (1,0,1), (1,0.5,0)]
    
      def draw(self):
        glEnable(GL_DEPTH_TEST)
    
        glLineWidth(5)
        glColor3fv((0, 0, 0))
        glBegin(GL_LINES)
        for e in self.edges:
            glVertex3fv(self.v[e[0]])
            glVertex3fv(self.v[e[1]])
        glEnd()
    
        glEnable( GL_POLYGON_OFFSET_FILL )
        glPolygonOffset( 1.0, 1.0 )
    
        glBegin(GL_QUADS)
        for i, quad in enumerate(self.surfaces):
            glColor3fv(self.colors[i])
            for iv in quad:
                glVertex3fv(self.v[iv])
        glEnd()
    
        glDisable( GL_POLYGON_OFFSET_FILL )