PDA

View Full Version : Multiple Subwindows Display List rendering problem [Python]



lucasgeras
07-04-2016, 05:05 PM
Hi. May I ask you to help me with the following problem. I wrote short application that contains two modules: .obj loader and viewer. I would like to display my .obj in two subwindows at once. Here is the code.
I tested my loader in single-windowed application and it works perfectly, when I call the displayList in render function. Unluckily it doesn't work for subwindows. In RenderGeometry() function i try to render my displaylist for both subwindows.
I am sure the model is loaded well, python doesnt generate any warnings too. Please tell me if there's any special routine for drawing displaylists in subwindows or possible bug in my or Opengl code? I would be very thankful for your help.


from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from staticOBJ import *

class game(object):
def __init__(self, posx, posy, resx, resy, window_label):
self.posx, self.posy = posx,posy
self.resx, self.resy = resx, resy
self.window_label = window_label
self.window = 1
self.rightEye, self.leftEye = 1,1
self.geometryList = []
################################################## ################################################## ###
#INIT GLUT
glutInit()
glutInitWindowSize(self.resx, self.resy)
glutInitWindowPosition(self.posx, self.posy)
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE)
self.window = glutCreateWindow(self.window_label)
glutDisplayFunc(self.Render)
################################################## ################################################## ##
#LOAD GEOMETRY
self.AddGeometry("temp.obj")
################################################## ################################################## ##
#INIT SUBWINDOWS
self.leftEye = glutCreateSubWindow(self.window,20,20,360,360)
glutDisplayFunc(self.leftEyeRender)
self.rightEye = glutCreateSubWindow(self.window,420,20,360,360)
glutDisplayFunc(self.rightEyeRender)
glutIdleFunc(self.RenderAll)
glutMainLoop()
################################################## ################################################## ##
#RENDER METHODS
def leftEyeRender(self):
glutSetWindow(self.leftEye)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)

glMatrixMode(GL_MODELVIEW)
glClearColor(0.0,0.0,0.2,1.0)
self.RenderGeometry()
glutSwapBuffers()
def rightEyeRender(self):
glutSetWindow(self.rightEye)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)

glMatrixMode(GL_MODELVIEW)
glClearColor(0.0,0.0,0.2,1.0)
self.RenderGeometry()
glutSwapBuffers()
def Render(self):
glutSetWindow(self.window)
glClear(GL_COLOR_BUFFER_BIT)
glClearColor(0.0,0.0,0.0,1.0)
glutSwapBuffers()
def RenderAll(self):
self.Render()
self.leftEyeRender()
self.rightEyeRender()
def RenderGeometry(self):
glColor3f(1.0,0.0,0.0)
glCallList(self.geometryList[0].gl_list)
#glutSolidCone(0.2,0.8,4,4)

################################################## ################################################## #
#GEOMETRY_METHODS

def AddGeometry(self,filename):
mesh = staticOBJ("temp.obj")
self.geometryList.append(mesh)

And the loader:


from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

class face(object):
def __init__(self):
self.vertexData = []
self.normalData = []
self.textureData = []
def AddVertex(self,new_value):
self.vertexData.append(new_value)
def AddNormal(self,new_value):
self.normalData.append(new_value)
def AddUV(self,new_value):
self.textureData.append(new_value)

class staticOBJ:
def __init__(self, filename):
self.vertices = []
self.normals = []
self.texcoords = []
self.facelist = []
################################################## ################################################
#PARSING OBJ FILE
for line in open(filename, "r"):
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
values.pop(0)
v = [0] * 3
for i in range(len(values)):
v[i] = float(values[i])
self.vertices.append(v)
elif values[0] == 'vn':
values.pop(0)
v = [0] * 3
for i in range(len(values)):
v[i] = float(values[i])
self.normals.append(v)
elif values[0] == 'vt':
values.pop(0)
v = [0] * 3
for i in range(len(values)):
v[i] = float(values[i])
self.texcoords.append(v)
elif values[0] == 'f':
tempface = face()
values.pop(0)
for i in range(len(values)):
a = values[i].split('/')
tempface.AddVertex(int(a[0]))
tempface.AddNormal(int(a[2]))
tempface.AddUV(int(a[1]))
self.facelist.append(tempface)
################################################## ################################################## #
#CREATING GLLIST
self.gl_list = glGenLists(1)
glNewList(self.gl_list, GL_COMPILE)
glFrontFace(GL_CCW)
glBegin(GL_QUADS)
for facenumber in range(0,len(self.facelist)):
for vertexnumber in range(0,len(self.facelist[facenumber].vertexData)):
vindex = self.facelist[facenumber].vertexData[vertexnumber] -1
nindex = self.facelist[facenumber].normalData[vertexnumber] -1
tindex = self.facelist[facenumber].textureData[vertexnumber] -1
glNormal3f(self.normals[nindex][0],self.normals[nindex][1],self.normals[nindex][2])
glTexCoord2f(self.texcoords[tindex][0], self.texcoords[tindex][1])
glVertex3f(self.vertices[vindex][0],self.vertices[vindex][1],self.vertices[vindex][2])
glEnd()
glEndList()
glShadeModel(GL_SMOOTH)

lucasgeras
07-06-2016, 08:43 AM
All right, I resolved the problem myself. It is not mentioned in the documentation so let me tell you how to do this, if somebody had the same problem.
glLists are not shared between windows contexts so it needs to be initialized for every subwindow every time. Heres the code:


self.leftEye = glutCreateSubWindow(self.window,20,20,360,360)
glutDisplayFunc(self.leftEyeRender)
self.gl_list = glGenLists(1)

...

self.rightEye = glutCreateSubWindow(self.window,20,20,360,360)
glutDisplayFunc(self.rightEyeRender)
self.gl_list = glGenLists(1)


And now you can call glCallList for both windows.

mhagain
07-06-2016, 08:53 AM
It is possible to share lists (and other GL objects, but - oddly - not (IIRC) VAOs), but it's platform specific: wglShareLists on Windows, for example.

lucasgeras
07-06-2016, 06:22 PM
Youre probably right;) I am the linux user so i wont even try;) Nevertheless I found the solution finally - opengl for python is unfortunately very poorly documented.

GClements
07-06-2016, 07:58 PM
glLists are not shared between windows contexts so it needs to be initialized for every subwindow every time.
If you're using FreeGLUT, you can use


glutSetOption(GLUT_RENDERING_CONTEXT, GLUT_USE_CURRENT_CONTEXT)


This makes subsequent calls to glutCreateWindow() or glutCreateSubWindow() associate the current context with the window rather than creating a new context.

Note that this isn't the same as creating a new context which shares data (display lists, textures, etc) with an existing context. It causes the windows to share the context itself, which means sharing everything. If your sub-windows have different state, you'll need to initialise that state at the beginning of the display callback (in particular, you can't set the projection matrix in the resize callback if the sub-windows might have different sizes).

If you want more flexibility that GLUT provides, use a more general GUI toolkit such as GTK, Qt or wxWidgets. GLUT was created to allow simple programs (primarily the example programs in the red book) to be created with a bare minimum of setup code.

GClements
07-06-2016, 08:06 PM
It is possible to share lists (and other GL objects, but - oddly - not (IIRC) VAOs)
According to the wiki (https://www.opengl.org/wiki/Container_Object#Object_Sharing), vertex array objects, framebuffer objects, transform feedback objects and program pipeline objects can't be shared. Other object types can be shared.

But that requires using something other than GLUT for context management.