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):
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()