GUIとOpenGLの組合せ

#Uncomment if you have multiple wxWidgets versions
#import wxversion
#wxversion.select('2.8')

import math, wx
from wx.glcanvas import GLCanvas
from OpenGL.GLU import *
from OpenGL.GL import *

class WxGLTest(GLCanvas):
    def __init__(self, parent):
        GLCanvas.__init__(self, parent,-1, attribList=[wx.glcanvas.WX_GL_DOUBLEBUFFER])
        wx.EVT_PAINT(self, self.OnDraw)
        wx.EVT_SIZE(self, self.OnSize)
        wx.EVT_MOTION(self, self.OnMouseMotion)
        wx.EVT_WINDOW_DESTROY(self, self.OnDestroy)
        
        self.init = True
        
    def OnDraw(self,event):
        self.SetCurrent()
        
        if not self.init:
            self.InitGL()
            self.init = False
            
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        
        # Draw the spiral in 'immediate mode'
        # WARNING: You should not be doing the spiral calculation inside the loop
        # even if you are using glBegin/glEnd, sin/cos are fairly expensive functions
        # I've left it here as is to make the code simpler.
        radius = 1.0
        x = radius*math.sin(0)
        y = radius*math.cos(0)
        glColor(0.0, 1.0, 0.0)
        glBegin(GL_LINE_STRIP)
        for deg in xrange(1000): 
            glVertex(x, y, 0.0)
            rad = math.radians(deg)
            radius -= 0.001
            x = radius*math.sin(rad)
            y = radius*math.cos(rad)
        glEnd()
        
        glEnableClientState(GL_VERTEX_ARRAY)
        
        spiral_array = []
        
        # Second Spiral using "array immediate mode" (i.e. Vertex Arrays)
        radius = 0.8
        x = radius*math.sin(0)
        y = radius*math.cos(0)
        glColor(1.0, 0.0, 0.0)
        for deg in xrange(820):
            spiral_array.append([x,y])
            rad = math.radians(deg)
            radius -= 0.001
            x = radius*math.sin(rad)
            y = radius*math.cos(rad)
            
        glVertexPointerf(spiral_array)
        glDrawArrays(GL_LINE_STRIP, 0, len(spiral_array))
        glFlush()
        self.SwapBuffers()
        return
        
    def InitGL(self):
        '''
        Initialize GL
        '''
        pass
        
    def OnSize(self, event):
        try:
            width, height = event.GetSize()
        except:
            width = event.GetSize().width
            height = event.GetSize().height
            
        self.Refresh()
        self.Update()
        
    def OnMouseMotion(self, event):
        x = event.GetX()
        y = event.GetY()
        
    def OnDestroy(self, event):
        print "Destroying Window"
        
if __name__ == '__main__':
    app = wx.App()
    frame = wx.Frame(None, -1, 'wxPython and OpenGL', wx.DefaultPosition, wx.Size(400,400))
    canvas = WxGLTest(frame)
    frame.Show()
    app.MainLoop()
import math
from OpenGL.GL import *
from OpenGL.GLU import *
from PyQt4 import QtGui
from PyQt4.QtOpenGL import *

class SpiralWidget(QGLWidget):
    '''
    Widget for drawing two spirals.
    '''
    def __init__(self, parent):
        QGLWidget.__init__(self, parent)
        self.setMinimumSize(500, 500)
        
    def paintGL(self):
        '''
        Drawing routine
        '''
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        
        # Draw the spiral in 'immediate mode'
        # WARNING: You should not be doing the spiral calculation inside the loop
        # even if you are using glBegin/glEnd, sin/cos are fairly expensive functions
        # I've left it here as is to make the code simpler.
        radius = 1.0
        x = radius*math.sin(0)
        y = radius*math.cos(0)
        glColor(0.0, 1.0, 0.0)
        glBegin(GL_LINE_STRIP)
        for deg in xrange(1000):
            glVertex(x, y, 0.0)
            rad = math.radians(deg)
            radius -= 0.001
            x = radius*math.sin(rad)
            y = radius*math.cos(rad)
        glEnd()
        
        glEnableClientState(GL_VERTEX_ARRAY)
        
        spiral_array = []
        
        # Second Spiral using "array immediate mode" (i.e. Vertex Arrays)
        radius = 0.8
        x = radius*math.sin(0)
        y = radius*math.cos(0)
        glColor(1.0, 0.0, 0.0)
        for deg in xrange(820):
            spiral_array.append([x, y])
            rad = math.radians(deg)
            radius -= 0.001
            x = radius*math.sin(rad)
            y = radius*math.cos(rad)
            
        glVertexPointerf(spiral_array)
        glDrawArrays(GL_LINE_STRIP, 0, len(spiral_array))
        glFlush()
        
    def resizeGL(self, w, h):
        '''
        Resize the GL window
        '''
        glViewport(0, 0, w, h)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(40.0, 1.0, 1.0, 30.0)
        
    def initializeGL(self):
        '''
        Initialize GL
        '''
        # set viewing projection
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClearDepth(1.0)
        
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(40.0, 1.0, 1.0, 30.0)
        
# You don't need anything below this
class SpiralWidgetDemo(QtGui.QMainWindow):
    ''' Example class for using SpiralWidget'''
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        widget = SpiralWidget(self)
        self.setCentralWidget(widget)
        
if __name__ == '__main__':
    app = QtGui.QApplication(['Spiral Widget Demo'])
    window = SpiralWidgetDemo()
    window.show()
    app.exec_()
# -*- coding: utf-8 -*-

import sys
import math
from PyQt4 import QtCore, QtGui, QtOpenGL
from OpenGL import GL, GLU

class GLWidget(QtOpenGL.QGLWidget):
  def __init__(self, parent=None):
    QtOpenGL.QGLWidget.__init__(self, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers), parent)
    self.xRot = 0
    self.yRot = 0
    self.zRot = 0
    self.lastPos = QtCore.QPoint()
    self.trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
    self.trolltechPurple = QtGui.QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

  def minimumSizeHint(self):
    return QtCore.QSize(50, 50)

  def sizeHint(self):
    return QtCore.QSize(150, 150)

  def setXRotation(self, angle):
    angle = self.normalizeAngle(angle)
    if angle != self.xRot:
      self.xRot = angle
      self.emit(QtCore.SIGNAL("xRotationChanged(int)"), angle)
      self.updateGL()

  def setYRotation(self, angle):
    angle = self.normalizeAngle(angle)
    if angle != self.yRot:
      self.yRot = angle
      self.emit(QtCore.SIGNAL("yRotationChanged(int)"), angle)
      self.updateGL()

  def setZRotation(self, angle):
    angle = self.normalizeAngle(angle)
    if angle != self.zRot:
      self.zRot = angle
      self.emit(QtCore.SIGNAL("zRotationChanged(int)"), angle)
      self.updateGL()

  def initializeGL(self):
    self.qglClearColor(self.trolltechPurple.dark())
    GL.glClearDepth(1.0)
    self.object = self.makeObject()
    #GL.glShadeModel(GL.GL_FLAT)
    GL.glShadeModel(GL.GL_SMOOTH)
    GL.glDepthFunc(GL.GL_LESS)
    GL.glEnable(GL.GL_DEPTH_TEST)
    GL.glEnable(GL.GL_CULL_FACE)

  def paintGL(self):
    GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
    GL.glLoadIdentity()
    GL.glTranslated(0.0, 0.0, -10.0)
    GL.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
    GL.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
    GL.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
    GL.glEnable(GL.GL_LIGHTING)
    GL.glEnable(GL.GL_LIGHT0)
    GL.glCallList(self.object)

  def resizeGL(self, width, height):
    side = min(width, height)
    GL.glViewport((width - side) / 2, (height - side) / 2, side, side)

    GL.glMatrixMode(GL.GL_PROJECTION)
    GL.glLoadIdentity()
    GL.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
    GL.glMatrixMode(GL.GL_MODELVIEW)

  def mousePressEvent(self, event):
    self.lastPos = QtCore.QPoint(event.pos())

  def mouseMoveEvent(self, event):
    dx = event.x() - self.lastPos.x()
    dy = event.y() - self.lastPos.y()

    if event.buttons() & QtCore.Qt.LeftButton:
      self.setXRotation(self.xRot + 8 * dy)
      self.setYRotation(self.yRot + 8 * dx)
    elif event.buttons() & QtCore.Qt.RightButton:
      self.setXRotation(self.xRot + 8 * dy)
      self.setZRotation(self.zRot + 8 * dx)

    self.lastPos = QtCore.QPoint(event.pos())

  def makeObject(self):
    vertices=[
          (-0.1, -0.1, -0.1), (0.1, -0.1, -0.1), (0.1, -0.1, 0.1), (-0.1, -0.1, 0.1),
          (-0.1, 0.1, -0.1), (0.1, 0.1, -0.1), (0.1, 0.1, 0.1), (-0.1, 0.1, 0.1),
        ]
    faces=[
          (0, 1, 2, 3), (7, 6, 5, 4), (1, 0, 4, 5), (2, 1, 5, 6), (3, 2, 6, 7), (0, 3, 7, 4)
        ]
    normals=[(0, -1, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 0, -1), (-1, 0, 0)]

    genList = GL.glGenLists(1)
    GL.glNewList(genList, GL.GL_COMPILE)
    GL.glEnable(GL.GL_NORMALIZE)
    GL.glBegin(GL.GL_QUADS)
    self.qglColor(self.trolltechGreen)

    for i in range(len(faces)):
      GL.glNormal3dv(normals[i])
      GL.glVertex(vertices[faces[i][0]])
      GL.glVertex(vertices[faces[i][1]])
      GL.glVertex(vertices[faces[i][2]])
      GL.glVertex(vertices[faces[i][3]])

    GL.glEnd()
    GL.glEndList()
    return genList

  def normalizeAngle(self, angle):
    while angle < 0:
      angle += 360 * 16
    while angle > 360 * 16:
      angle -= 360 * 16
    return angle

class Window(QtGui.QWidget):
  def __init__(self, parent=None):
    QtGui.QWidget.__init__(self, parent)
    self.glWidget = GLWidget()
    mainLayout = QtGui.QHBoxLayout()
    mainLayout.addWidget(self.glWidget)
    self.setLayout(mainLayout)
    self.setWindowTitle(self.tr("Hello GL"))

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  window = Window()
  window.show()
  sys.exit(app.exec_())