2

I am using an approach for hidden line removal in a PyOpenGL program where I draw a figure twice, once as a wireframe and then again as filled polygons. It is working fine for my own figures but not for the basic glutSolidCube/glutWireCube so I am curious if there is a flaw in my code that the use of glut figures is exposing. Maybe there is just something squirrelly in the glut figures but I am guessing those are pretty well used and debugged...

here is my draw code (working app follows), followed by screen shot of result:

def render_scene():
    glEnableClientState(GL_VERTEX_ARRAY)
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLineWidth(2)

    glMatrixMode(GL_MODELVIEW)
    glPushMatrix()
    
    glRotate(rot[0], 1, 0, 0)
    glRotate(rot[1], 0, 1, 0)
    #
    # =============
    # pass 1: lines
    # =============
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)    
    glColor(0, 0, 0)
    # my cube
    glVertexPointer(3, GL_FLOAT, 0, cube_vertices)
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cube_indices)
    # glut cube
    glPushMatrix()
    glTranslate(-1.1, 0, 0)
    glutWireCube(1)
    glPopMatrix()
    #
    # ================
    # pass 2: filled polygons
    # ================
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    glEnable(GL_POLYGON_OFFSET_FILL)
    glPolygonOffset(2, 2)
    glColor(1, 1, 1)
    # my cube
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cube_indices)
    # glut cube
    glPushMatrix()
    glTranslate(-1.1, 0, 0)
    glutSolidCube(1)
    glPopMatrix()
   
    glPopMatrix()
    pg.display.flip()
    return

Thanks in advance!

running code:

import pygame as pg
from pygame.locals import *
from numpy import array, float32, uint32
from OpenGL.GLUT import *
from OpenGL.GL import *
from OpenGL.GLU import *

FPS = 60
WIDTH = 800
HEIGHT = 600
clock = pg.time.Clock()
rot = [10, 10]

cube_vertices = array([
    -0.5, -0.5, -0.5,
    0.5, -0.5, -0.5,
    0.5, 0.5, -0.5,
    -0.5, 0.5, -0.5,
    -0.5, -0.5, 0.5,
    0.5, -0.5, 0.5,
    0.5, 0.5, 0.5,
    -0.5, 0.5, 0.5], dtype=float32)   

cube_indices = array([
    0, 1, 2, 3,   # front 
    4, 5, 1, 0,   # top
    3, 2, 6, 7,   # bottom
    5, 4, 7, 6,   # back
    1, 5, 6, 2,   # right
    4, 0, 3, 7], dtype=uint32)    


def setup_rc():
    
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_CULL_FACE)
    glCullFace(GL_FRONT)
    glClearColor(1, 1, 1, 0)  
    
    pg.event.post(pg.event.Event(VIDEORESIZE, {'size':(WIDTH, HEIGHT)}))

    return


def on_video_resize(event):
    w = event.size[0]
    h = event.size[1]
    if h == 0: h = 1
    aspect_ratio = w/h

    glViewport (0, 0, w, h)
    glMatrixMode (GL_PROJECTION)
    glLoadIdentity()
    if w <= h:
        glOrtho (-1.5, 1.5, -1.5*h/w, 1.5*h/w, -10.0, 10.0)
    else:
        glOrtho (-1.5*w/h, 1.5*w/h, -1.5, 1.5, -10.0, 10.0)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

    return True

def render_scene():
    glEnableClientState(GL_VERTEX_ARRAY)
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLineWidth(2)

    glMatrixMode(GL_MODELVIEW)
    glPushMatrix()
    
    glRotate(rot[0], 1, 0, 0)
    glRotate(rot[1], 0, 1, 0)
    #
    # =============
    # pass 1: lines
    # =============
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)    
    glColor(0, 0, 0)
    # my cube
    glVertexPointer(3, GL_FLOAT, 0, cube_vertices)
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cube_indices)
    # glut cube
    glPushMatrix()
    glTranslate(-1.1, 0, 0)
    glutWireCube(1)
    glPopMatrix()
    #
    # ================
    # pass 2: filled polygons
    # ================
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    glEnable(GL_POLYGON_OFFSET_FILL)
    glPolygonOffset(2, 2)
    glColor(1, 1, 1)
    # my cube
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cube_indices)
    # glut cube
    glPushMatrix()
    glTranslate(-1.1, 0, 0)
    glutSolidCube(1)
    glPopMatrix()
   
    glPopMatrix()
    pg.display.flip()
    return

def update():
    clock.tick(FPS)
    return

def on_keydown(event):
    key = event.key
    if key == K_LEFT:
        rot[1] -= 2
    elif key == K_RIGHT:
        rot[1] += 2
    if key == K_UP:
        rot[0] -= 2
    elif key == K_DOWN:
        rot[0] += 2
    elif key == K_ESCAPE:    
        pg.event.post(pg.event.Event(QUIT))
    return True

def main():
    pg.init()
    pg.display.set_mode((WIDTH, HEIGHT), DOUBLEBUF|OPENGL|RESIZABLE)
    pg.key.set_repeat(200, 100)
    pg.display.set_caption("Use arrow keys to rotate scene")
    glutInit()

    setup_rc()
    
    add_event_handler(VIDEORESIZE, on_video_resize)
    add_event_handler(KEYDOWN, on_keydown)
    
    while do_events():
        render_scene()
        update()

    pg.quit()
    return 

# =======================================
# my simplified pygame event handling, 
# normally in a separate module but wanted
# to make this code standalone
# =======================================
#
event_map = {pg.QUIT : (lambda e: False)}

def add_event_handler(key, func):  
    event_map[key] = func
    return

def try_to_apply(e):
    try:
        return event_map[e.type](e)
    except KeyError:
        return True

def do_events():
    return all(try_to_apply(e) for e in pg.event.get())

# ========================================

main()

Screen shot (glut-based figure on left, my figure on right): enter image description here

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
PaulM
  • 305
  • 1
  • 8
  • Please show the result. – Yves Daoust Aug 21 '23 at 20:28
  • @YvesDaoust original post edited to show result, thanks. – PaulM Aug 21 '23 at 20:34
  • Thanks @Rabbid76, in my haste to post a working sample I left that out by mistake and adding it back had no effect. – PaulM Aug 21 '23 at 20:43
  • @Rabbid76 the code should work in any python environment with PyOpenGL and pygame, but the draw code itself is pretty standard. I am not concerned about using the glut cubes but wondering if there is a flaw in my approach for hidden line removal that my simple figures today don't expose. – PaulM Aug 21 '23 at 20:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/254992/discussion-between-paulm-and-rabbid76). – PaulM Aug 21 '23 at 21:12

1 Answers1

2

The problem is that you are mixing face culling and polygon offsets. The winding order of glutSolidCube/glutWireCube seems to be the opposite of the winding order of your own meshes. Disable face culling. Also note that glutSolidCube/glutWireCube may change the client states, so you should always specify the vertex pointer with glVertexPointer before drawing a geometry:

def setup_rc():    
    glEnable(GL_DEPTH_TEST)
    #glEnable(GL_CULL_FACE)
    #glCullFace(GL_FRONT)
    glClearColor(1, 1, 1, 0)  
def render_scene():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLineWidth(2)

    glMatrixMode(GL_MODELVIEW)
    glPushMatrix()
    
    glRotate(rot[0], 1, 0, 0)
    glRotate(rot[1], 0, 1, 0)
    #
    # =============
    # pass 1: lines
    # =============
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)  
    glDisable(GL_POLYGON_OFFSET_FILL)  
    glColor(0, 0, 0)
    # my cube
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, cube_vertices)
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cube_indices)
    # glut cube
    glPushMatrix()
    glTranslate(-1.1, 0, 0)
    glutWireCube(1)
    glPopMatrix()
    #
    # ================
    # pass 2: filled polygons
    # ================
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    glEnable(GL_POLYGON_OFFSET_FILL)
    glPolygonOffset(2, 2)
    glColor(1, 1, 0)
    # my cube
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, cube_vertices)
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cube_indices)
    # glut cube
    glPushMatrix()
    glTranslate(-1.1, 0, 0)
    glutSolidCube(1)
    glPopMatrix()
   
    glPopMatrix()
    glFlush()

Rabbid76
  • 202,892
  • 27
  • 131
  • 174