[PYTHON] Sélection de l'interface graphique PyOpenGL et séparation du dessin et de l'interface graphique

Avant de passer à Shader ou VBO, organisez la connexion entre GUI et PyOpenGL. PyOpenGL peut être exécuté avec diverses interfaces graphiques, mais s'il s'agit d'un échantillon, il ne fera que surpasser, alors je vais organiser cette zone. S'il s'agit d'une application légèrement compliquée, vous souhaitez afficher une liste ou une arborescence à côté.

L'environnement est Windows 10 (64 bits) + python3.5 d'Anaconda (64 bits)

glut Pour une raison quelconque, OpenGL commence ici. Étant donné que le thème consiste à séparer le dessin et l'interface graphique, la partie qui dessine uniquement OpenGL est la suivante.

simple_renderer.py


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

def initialize():
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClearDepth(1.0)
    glDepthFunc(GL_LESS)
    glEnable(GL_DEPTH_TEST)

def resize(Width, Height):
    # viewport
    if Height == 0:
        Height = 1
    glViewport(0, 0, Width, Height)
    # projection
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)

def draw():
    # clear
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    # view
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

    # model
    glTranslatef(0.0, 0.0, -6.0)
    glBegin(GL_POLYGON)
    glVertex3f(0.0, 1.0, 0.0)
    glVertex3f(1.0, -1.0, 0.0)
    glVertex3f(-1.0, -1.0, 0.0)
    glEnd()

    glFlush()

Code qui appelle simple_renderer depuis glut.

simple_glut.py


from OpenGL.GLUT import *
import sys
import simple_renderer


def reshape_func(w, h):
    simple_renderer.resize(w, h == 0 and 1 or h)

def disp_func():
    simple_renderer.draw()
    glutSwapBuffers()

if __name__=="__main__":
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
    glutInitWindowSize(256, 256)
    glutCreateWindow(b"triangle")
    glutDisplayFunc(disp_func)
    glutIdleFunc(disp_func)
    glutReshapeFunc(reshape_func)

    simple_renderer.initialize()

    glutMainLoop()

simple_glut.png

Drawing (simple_renderer.py) ne connaît pas la surabondance, et GUI (simple_gtlut.py) ne connaît pas OpenGL. Donc, je veux partager la partie simple_renderer.py avec chaque interface graphique.

bibliothèque de colle

J'ai créé une bibliothèque qui étend simple_renderer.py et peut être décrite comme suit.

https://github.com/ousttrue/glglue

controller_sample.py


# coding: utf-8
from OpenGL.GL import *


class Controller(object):
    def __init__(self):
        pass

    def onResize(self, w, h):
        glViewport(0, 0, w, h)

    def onLeftDown(self, x, y):
        print('onLeftDown', x, y)

    def onLeftUp(self, x, y):
        print('onLeftUp', x, y)

    def onMiddleDown(self, x, y):
        print('onMiddleDown', x, y)

    def onMiddleUp(self, x, y):
        print('onMiddleUp', x, y)

    def onRightDown(self, x, y):
        print('onRightDown', x, y)

    def onRightUp(self, x, y):
        print('onRightUp', x, y)

    def onMotion(self, x, y):
        print('onMotion', x, y)

    def onWheel(self, d):
        print('onWheel', d)

    def onKeyDown(self, keycode):
        print('onKeyDown', keycode)

    def onUpdate(self, d):
        print('onUpdate', d)

    def draw(self):
        glClearColor(0.9, 0.5, 0.0, 0.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glBegin(GL_TRIANGLES)
        glVertex(-1.0,-1.0)
        glVertex( 1.0,-1.0)
        glVertex( 0.0, 1.0)
        glEnd()

        glFlush()


if __name__=="__main__":
    controller=Controller()
    import glglue.glut
    glglue.glut.mainloop(controller, width=640, height=480, title=b"sample")    

Appelez directement l'API Win32

Vous ne devriez pas simplement créer une fenêtre avec des ctypes. python a la capacité d'appeler dll avec ctypes, alors faites-le. C'était la seule méthode sous Windows qui ne nécessitait pas d'installation supplémentaire, Si vous utilisez Anaconda, PyQt4 convient. C'est un mérite que vous puissiez partitionner vous-même la boucle principale.

wgl_sample.py


import controller_sample
import glglue.wgl

if __name__=="__main__":
    controller=controller_sample.Controller()
    glglue.wgl.mainloop(controller, width=640, height=480, title=b"sample")

tkinter Un wrapper python Tcl / TK fourni avec Python sobrement. Malheureusement, j'ai besoin d'installer une DLL supplémentaire (TOGL) pour le widget OpenGL Par conséquent, il ne peut pas être utilisé immédiatement sans rien faire. Si vous n'utilisez pas Anaconda et que vous souhaitez économiser du stockage, vous pouvez l'utiliser.

Postscript

J'étais en train de modifier (↓) pour remplacer la vue 3D de PMCA par TOGL, mais j'ai découvert que TOGL n'est pas supporté plus que prévu.

http://togl.sourceforge.net/

Vous pouvez télécharger la version 32 bits de TOGL2.0.dll avec TCL / TK, qui est compatible avec TCL / TK jusqu'à 3.3. Cela ne fonctionne pas après 3.4. Il n'y a pas de version 64 bits de dll en premier lieu.

De plus, Accueil de PyOpenGL Eu les mises en garde suivantes. TOGL semble difficile à compiler.

Note that Togl support is deprecated, it's there for legacy code (once you compile Togl), but you should choose a GUI library that has OpenGL support built-in for any new development. Togl support has been dropped due to the complexity of compilation and the headache of maintenance. There are projects which attempt to provide Togl support, feel free to install those into your Python's Tk installation if you need Togl under Python.

L'icône rouge est la preuve de TOGL.

pmca_ss.png

TOGL était une option possible compte tenu de l'effort d'installation et de la multiplateforme. C'est hors de support.

L'erreur d'incompatibilité Python3 suivante a-t-elle été laissée sans surveillance indique également que TOGL n'est pas pris en charge?

glglue> c:\Anaconda3\python.exe tkinter_sample.py
Traceback (most recent call last):
  File "tkinter_sample.py", line 3, in <module>
    import glglue.togl
  File "D:\dev\_python\glglue\glglue\togl.py", line 4, in <module>
    import OpenGL.Tk
  File "c:\Anaconda3\lib\site-packages\OpenGL\Tk\__init__.py", line 102, in <mod
ule>
    if sys.maxint > 2**32:
AttributeError: module 'sys' has no attribute 'maxint'

Modifiez sys.maxint en sys.maxsize.

PyQt4 Il a été inclus dans Anaconda. PyQt5 est bon de toute façon, Pour le moment, c'est mon préféré.

pyqt4_sample.py


from PyQt4 import Qt
import controller_sample
import glglue.qgl
class Window(Qt.QWidget):
    def __init__(self, parent=None):
        Qt.QWidget.__init__(self, parent)
        # setup opengl widget
        self.controller=controller_sample.Controller()
        self.glwidget=glglue.qgl.Widget(self, self.controller)
        # packing
        mainLayout = Qt.QHBoxLayout()
        mainLayout.addWidget(self.glwidget)
        self.setLayout(mainLayout)

import sys
app = Qt.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())

Résumé

J'aime PyQt4 chez Anaconda.

À l'avenir, VBO et Shader seront planifiés avec numpy.

Recommended Posts

Sélection de l'interface graphique PyOpenGL et séparation du dessin et de l'interface graphique
Séparation de la conception et des données dans matplotlib
Séparation du nom et du prénom japonais avec BERT
Sélection des données de mesure