Reputation: 21
here is my QGLWidget class for drawing 3d meshes by openGL
class OpenGLWidget1(QGLWidget):
#def init(self,fdir,filename,swapyz=False):
#self.fdir=fdir
#self.filename=filename
#self.swapyz=swapyz
#self.initializeObj()
def initializeObj(self):
self.vertices=[]
self.normals=[]
self.texcoords=[]
self.faces=[]
self.mtl=[self.fdir,"no_mtllib_file"]
self.material="color0"
for line in open(self.fdir+self.filename,"r"):
if line.startswith('#'):continue
values=line.split()
if not values:continue
if values[0] == 'v' :
v=[float(values[1]),float(values[2]),float(values[3])]
if self.swapyz:
v = v[0],v[2],v[1]
self.vertices.append(v)
elif values[0] == 'vn':
v=[float(values[1]),float(values[2]),float(values[3])]
if self.swapyz:
v = v[0],v[2],v[1]
self.normals.append(v)
elif values[0] == 'vt':
v=[float(values[1]),float(values[2])]
self.texcoords.append(v)
elif values[0] == 'usemtl':
self.material=values[1]
elif values[0] == 'mtllib':
self.mtl=[self.fdir,values[1]]
elif values[0] == 'f':
face=[]
texcoords=[]
norms=[]
for v in values[1:]:
w=v.split('/')
face.append(int(w[0]))
if len(w)>=2 and len(w[1])>0:`
texcoords.append(int(w[1]))
else:
texcoords.append(0)
if len(w)>=3 and len(w[2])>0:
norms.append(int(w[2]))
else:
norms.append(0)
self.faces.append((face,norms,texcoords,self.material))
def create_bbox(self):
ps=np.array(self.vertices)
vmin=ps.min(axis=0)
vmax=ps.max(axis=0)
self.bbox_center=(vmax+vmin)/2
self.bbox_half_r=np.max(vmax-vmin)/2
def create_gl_list(self):
self.mtl=MTL(*self.mtl)
self.gl_list=glGenLists(1)
glNewList(self.gl_list,GL_COMPILE)
glEnable(GL_TEXTURE_2D)
glFrontFace(GL_CCW)
for face in self.faces:
vertices,normals,texture_coords,material=face
mtl=self.mtl[material]
glColor(*mtl['kd'])
glBegin(GL_POLYGON)
for i in range(len(vertices)):
if normals[i]>0:
glNormal3fv(self.normals[normals[i]-1])
if texture_coords[i]>0:
glTexCoord2fv(self.texcoords[texture_coords[i]-1])
glVertex3fv(self.vertices[vertices[i]-1])
glEnd()
glDisable(GL_TEXTURE_2D)
glEndList()
def initializeGL(self):
self.fdir = "/home/pczebra/pig9/outModel/"
self.filename = "model101_out.obj"
self.swapyz = True
self.initializeObj()
glViewport(0, 0, self.geometry().width(), self.geometry().height())
self.create_bbox()
light.setup_lighting()
glLightfv(GL_LIGHT0,GL_POSITION,(0,0,-1000,0.0))
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
self.create_gl_list()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
cam=light.camera
cam.Ortho.bbox[:]=cam.Ortho.bbox * 13
cam.Ortho.nf[:]=cam.Ortho.nf * 20
glOrtho(*cam.Ortho.params)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_MODELVIEW)
self.rx,self.ry=(0,0)
self.tx,self.ty=(0,0)
self.zpos=5
def paintGL(self):
#glViewport(0,0,self.geometry().width(),self.geometry().height())
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glTranslate(self.tx/20. , self.ty/20. , - self.zpos)
glRotate(self.ry/5,1,0,0)
glRotate(self.rx/5,0,0,1)
s=[10/self.bbox_half_r]*3
glScale(*s)
t=-self.bbox_center
glTranslate(*t)
glCallList(self.gl_list)
def resizeGL(self, width, height):
glViewport(0,0,width,height)
def mousePressEvent(self, QMouseEvent):
if Qt.LeftButton == QMouseEvent.button():
self.lastPos=QMouseEvent.pos()
if Qt.RightButton == QMouseEvent.button():
self.lastPos=QMouseEvent.pos()
def mouseMoveEvent(self, QMouseEvent):
if QMouseEvent.buttons() and Qt.LeftButton:
a=QMouseEvent.pos()
dx=a.x()-self.lastPos.x()
dy=a.y()-self.lastPos.y()
dx=dx/2
dy=dy/2
self.rx -=dx
self.ry -=dy
self.updateGL()
if QMouseEvent.buttons() and Qt.RightButton:
a=QMouseEvent.pos()
dx = a.x() - self.lastPos.x()
dy = a.y() - self.lastPos.y()
dx = dx / 2
dy = dy / 20
self.tx += dx
self.ty -= dy
self.updateGL()
self.lastPos=QMouseEvent.pos()
then i have two QGLWidgets in pyqt, to instant the class
def w1(self):
self.glWidget = OpenGLWidget1(self)
self.glWidget.setGeometry(QRect(30, 540, 651, 401))
self.glWidget.show()
def w2(self):
self.glWidget_raw = OpenGLWidget1(self)
#self.glWidget_raw.init(fdir,filename, swapyz=True)
self.glWidget_raw.setGeometry(QRect(30, 50, 651, 401))
self.glWidget_raw.show()
def visualization(self, checked):
self.w1()
self.w2()
and show
the second QGLWidget and the later QGLWidget always has trouble with gl size, they can not show normally anyway! How can i fix the problem.
Upvotes: 2
Views: 175
Reputation: 162164
Most of such scaling problems come down to not following best practices. For some reasons, practically all early tutorials on OpenGL, written when OpenGL itself was fairly new, placed setting the viewport size and setting the projection matrix in the reshape handler. Similarly a lot of stuff was done in the initialization code, which actually belongs into the display code.
These tutorials got away with that, because these tutorials were entirely self contained and didn't have to interact with a larger program. You're using the Qt framework, which internally also makes use of OpenGL do draw stuff. So you have to be prepared to live with that.
Here are the basic rules for living with OpenGL:
Initialization code: will do only things that will not have any observable effect on the generated image. Anything that influences the data flow of the rendering process, i.e. render pipeline state should not be set in initialization code. – Things to do in initialization code would be loading assets, i.e. models, textures and – in your case – setting up display lists¹.
render target reshape code: Like initialization code this should not do anything that influences the actual rendering data flow. You use it to initialize resources, which parameters depend on the size and location of the render target. The viewport and the scissor rectangle are not part of the render target parameters! – Things to do in render target reshape code is allocating Framebuffer Objects and their attechment Render Buffers or target textures.
drawing code proper: The bulk of graphics API operations should be placed here. The typical order of operations is:
Note that each of these steps may happen several times throughout rendering a single image, the above is just the rough outline. Also the order may change, for example for a given set of drawing data multiple viewports may be rendered to, so the above ordering is not set in stone. It depends on your application.
Anyway, your program code as things that are considered drawing code all over the place, and that's likely a huge part of your problem.
1: On a side note: Whoa, display lists, well that's a blast from the past. I mean, display lists used to be kind of cool, massively accelerated things, wenn doing remote rendering though X11-over-TCP. But that's been out of fashion for now – what – something like 15 years or so. Don't use it. Also don't use GL_POLYGON. Your data obviously is a list of triangles (and maybe some quads), so just put them into an array, in order, load that into a vertex array and call glDrawArrays
on that. That's how you're supposed to do it for over 20 years. Don't follow a programming model, that's been outdated for almost the quarter of a century!
Upvotes: 1