Search code examples
pythonopenglbufferredraw

How to add vertexes in OpenGL scene when its already loaded?


I'm using python to make a Rubik's cube application with OpenGL and pyGame. I can see the cube and I want to press a button and load the colors, but colors are not shown. (I color each little cube alone but I don't think that it matters).

If I call the function that colors the cube in the function which draws the vertexes for the cube (at the start of the program), the colors are perfectly shown, but if i call the color function with the press of a key (using pyGame) while the application is already running they don't.

the function that colors a little cube:

def color_cubie(self):
    surfaces = (
        (0, 1, 2, 3),
        (4, 5, 6, 7),
        (0, 3, 7, 4),
        (1, 2, 6, 5),
        (2, 3, 7, 6),
        (0, 1, 5, 4)
        )
    colors = [
        (1, 0, 0), (1, 0.5, 0),   
        (0, 1, 0), (0, 0, 1),          
        (1, 1, 1), (1, 1, 0)     
        ]

    #faces
    glBegin(GL_QUADS)
    index=0
    for surface in surfaces:
        glColor3fv(colors[index])
        for vertex  in surface:
            glVertex3fv(self.verticies[vertex])
        index+=1
    glEnd()

the part that I call the function (the if statement is true when i press c key in keyboard). Also cube is a 3x3x3 numpy array which is filled with cubie objects.

if move == "c":
    for row in self.cube[2]:
        for cubie in row:
            cubie.color_cubie()

the main/ render function:


def render():
    pygame.init()
    display = (WIDTH, HEIGHT)
    screen = pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
    pygame.display.set_caption("Rubiks Cube")

    glEnable(GL_DEPTH_TEST)
    glClearColor(1, 1, 1, 1)
    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
    glTranslatef(0.0, 0.0, -7)
    glLineWidth(10)

    while True:              
        mouse_pos = pygame.mouse.get_rel()
        glRotatef(1, mouse_pos[1], mouse_pos[0], 0)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        #create cube object
        new_cube = Cube()
        new_cube.show_cube()

        pygame.display.flip()
        pygame.time.wait(10)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == K_c:
                    new_cube.rotate_cube("c")

As I read i must redraw the screen in order to see the colored cube. But glClear(...) doesn't do that?


Solution

  • new_cube.rotate_cube("c") is only executed once, when the key is pressed. This causes that the colors only flash for a short moment.

    You have to add a state (self.colored) to the class Cube, which indicates if the colored cube or the lines hav to be drawn. When new_cube.color_cubie is called the change th state of the variable:

    e.g.

    class Cube:
    
        def __init__(self):
            self.colored = False
            # [...]
    
        def color_cubie(self):
            self.colored = True # change state, from now on draw colored 
    
        def show_cube(self)
            if self.colored:
                self.drawColored()
            else:
                self.drawLines()
    
    
        def drawLines(slef):
            # draw the lines here
            # [...]
    
    
        def drawColored(self):
            # draw the colored cube here
             # [...]