Python QGLWidget无法正常初始化
下面是我的QGLWidget类,用于通过openGL绘制3d网格Python QGLWidget无法正常初始化,python,opengl,pyqt5,qglwidget,Python,Opengl,Pyqt5,Qglwidget,下面是我的QGLWidget类,用于通过openGL绘制3d网格 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.vertic
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()
然后我在pyqt中有两个QGLWidget,用于使类即时化
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()
展示
第二个QGLWidget和后一个QGLWidget的gl大小总是有问题,它们无论如何都不能正常显示!如何解决此问题。大多数此类缩放问题归结为未遵循最佳实践。出于某些原因,几乎所有关于OpenGL的早期教程(在OpenGL本身相当新的时候编写)都将设置视口大小和设置投影矩阵放置在重塑处理程序中。类似地,在初始化代码中完成了很多工作,而初始化代码实际上属于显示代码 这些教程没有受到影响,因为这些教程是完全独立的,不必与大型程序交互。您使用的是Qt框架,它在内部也使用OpenGL的do draw工具。所以你必须准备好接受这一切 以下是使用OpenGL的基本规则: 初始化代码:只执行对生成的图像没有任何可见影响的操作。不应在初始化代码中设置影响渲染过程数据流的任何内容,即渲染管道状态在初始化代码中要做的事情是加载资产,即模型、纹理和(在您的情况下)设置显示列表 渲染目标重塑代码:与初始化代码一样,这不应影响实际渲染数据流。使用它初始化资源,这些参数取决于渲染目标的大小和位置。视口和剪刀形矩形不是渲染目标参数的一部分渲染目标重塑代码中要做的事情是分配帧缓冲区对象及其attechment渲染缓冲区或目标纹理 正确的绘图代码:大部分图形API操作应该放在这里。典型的操作顺序是: 选择“渲染目标” 设置视口并清除(&R) 绑定保存图形数据的缓冲区 设置渲染管道状态深度测试、着色器、纹理等。 画画 成品图 请注意,在渲染单个图像的过程中,这些步骤可能会发生多次,以上只是粗略的轮廓。此外,顺序可能会更改,例如,对于一组给定的图形数据,多个视口可能会被渲染到其中,因此上述顺序不是一成不变的。这取决于你的申请 无论如何,你的程序代码被认为是到处都在画代码的东西,这可能是你的问题的很大一部分
1:附带说明:哇,显示列表,这是过去的爆炸。我的意思是,显示列表过去是一种很酷的、大规模加速的东西,我们通过TCP上的X11进行远程渲染。但这已经过时15年左右了。不要用它。也不要使用GL_多边形。很明显,你的数据是一个三角形列表,可能还有一些四边形,所以把它们放在一个数组中,按顺序,加载到一个顶点数组中,然后调用gldrawArray。20多年来你都应该这样做。不要遵循编程模型,它已经过时了将近四分之一个世纪了 谢谢你的建议,它们很有帮助。因为我是OpenGL中的一只新蜜蜂,所以有很多麻烦困扰着我。幸运的是,我已经解决了这个问题。似乎我在以下代码中遇到了问题:cam=light.camera-cam.Ortho.bbox[:]=cam.Ortho.bbox*13 cam.Ortho.nf[:]=cam.Ortho.nf*20 glOrtho*cam.Ortho.params与摄影机距离有关,我不知道为什么cam.Ortho.params会不断变化,首先,cam.Ortho.params=[-12,12.,-12,12,22.,-22.],但是,通过第二个实例,cam.Ortho.params大约[-600600,-600600800800],并导致了问题。因此我将glOrtho-12设置为,12. ,-12. ,12. ,22. ,-22.它成功了!