QGLWidget не может быть нормально инициализирован - PullRequest
0 голосов
/ 01 ноября 2018

вот мой класс QGLWidget для рисования 3d-сеток с помощью 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()

тогда у меня есть два QGLWidget в pyqt, чтобы мгновенно получить класс

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

и шоу

image of runing result

второй QGLWidget и более поздний QGLWidget всегда имеют проблемы с размером gl, они все равно не могут нормально отображаться! Как я могу решить проблему.

1 Ответ

0 голосов
/ 01 ноября 2018

Большинство таких проблем масштабирования сводятся к несоблюдению лучших практик. По некоторым причинам практически все ранние учебники по OpenGL, написанные, когда сам OpenGL был довольно новым, помещали установку размера области просмотра и установку матрицы проекции в обработчике изменения формы. Точно так же много чего было сделано в коде инициализации, который фактически принадлежит к коду отображения.

Эти учебники обходились без этого, потому что эти учебники были полностью автономными и не должны взаимодействовать с более крупной программой. Вы используете инфраструктуру Qt, которая внутренне также использует OpenGL для рисования. Так что вы должны быть готовы жить с этим.

Вот основные правила жизни в OpenGL:

  • Код инициализации: будет делать только то, что не окажет заметного влияния на сгенерированное изображение. Все, что влияет на поток данных процесса рендеринга, то есть состояние конвейера рендеринга , должно не быть установлено в коде инициализации. - В коде инициализации необходимо выполнить загрузку ресурсов, то есть моделей, текстур и, в вашем случае, настроить списки отображения.

  • целевой код преобразования формы: Как и код инициализации, он не должен делать ничего, что влияет на фактический поток данных рендеринга. Вы используете его для инициализации ресурсов, параметры которых зависят от размера и местоположения цели рендеринга. Окно просмотра и прямоугольник ножниц не являются частью целевых параметров рендеринга! - В коде изменения формы целевого объекта рендеринга необходимо выделить Объекты Framebuffer и их обслуживание Визуализация буферов или целевых текстур .

  • собственно код рисования: Большая часть операций графического API должна быть размещена здесь. Типичный порядок операций:

    1. выберите цель рендеринга
    2. установить видовой экран и очистить
    3. связать буферы, содержащие данные чертежа
    4. установить состояние конвейера рендеринга (тестирование глубины, шейдеры, текстуры и т. Д.)
    5. рисовать вещи
    6. Готовый чертеж

    Обратите внимание, что каждый из этих этапов может происходить несколько раз при рендеринге одного изображения. Выше приведен только грубый контур. Также порядок может измениться, например, для заданного набора данных чертежа может быть отображено несколько видовых экранов, поэтому приведенный выше порядок не задан в камне. Это зависит от вашей заявки.

В любом случае, ваш программный код - это то, что считается кодом для рисования повсюду, и это, вероятно, огромная часть вашей проблемы.


1: С другой стороны: показывает списки , ну, это взрыв из прошлого. Я имею в виду, что списки отображения раньше были классными, с огромным ускорением, когда мы делали удаленный рендеринг через X11-over-TCP. Но сейчас это вышло из моды - что-то около 15 лет или около того. Не используйте это. Также не используйте GL_POLYGON. Ваши данные, очевидно, представляют собой список треугольников (и, возможно, некоторых квадратов), поэтому просто поместите их в массив, по порядку, загрузите его в массив вершин и вызовите glDrawArrays для этого. Вот как вы должны делать это более 20 лет. Не следуйте модели программирования, которая устарела почти четверть века!

...