Sunday, February 05, 2012

Proof of concept OpenGL program in python and Qt/PySide

Here is the output of my initial test program:




I am planning to test the performance of various ways of rendering lots of spheres using OpenGL. I will use python and Qt to run the tests. As a first step, I have created a very light hello program that renders the classic Utah teapot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/python
 
# File teapot_test.py
# "hello world" type rendering of the classic Utah teapot
# Requires python modules PySide and PyOpenGL
 
from PySide.QtGui import QMainWindow, QApplication
from PySide.QtOpenGL import QGLWidget
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
import sys
 
 
def override(interface_class):
  """
  Method to implement Java-like derived class method override annotation.
  Courtesy of mkorpela's answer at
  """
  def override(method):
      assert(method.__name__ in dir(interface_class))
      return method
  return override
 
 
class SphereTestGLWidget(QGLWidget):
  "GUI rectangle that displays a teapot"
  @override(QGLWidget)
  def initializeGL(self):
      "runs once, after OpenGL context is created"
      glEnable(GL_DEPTH_TEST)
      glClearColor(1,1,1,0) # white background
      glShadeModel(GL_SMOOTH)
      glEnable(GL_COLOR_MATERIAL)
      glMaterialfv(GL_FRONT, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
      glMaterialfv(GL_FRONT, GL_SHININESS, [50.0])
      glLightfv(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
      glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0])
      glLightfv(GL_LIGHT0, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
      glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [1.0, 1.0, 1.0, 0.0])
      glEnable(GL_LIGHTING)
      glEnable(GL_LIGHT0)
      self.orientCamera()
      gluLookAt(0, 0, -10, # camera
                0, 0, 0, # focus
                0, 1, 0) # up vector
     
  @override(QGLWidget)
  def paintGL(self):
      "runs every time an image update is needed"
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
      self.paintTeapot()
     
  @override(QGLWidget)
  def resizeGL(self, w, h):
      "runs every time the window changes size"
      glViewport(0, 0, w, h)
      self.orientCamera()
     
  def orientCamera(self):
      "update projection matrix, especially when aspect ratio changes"
      glPushAttrib(GL_TRANSFORM_BIT) # remember current GL_MATRIX_MODE
      glMatrixMode(GL_PROJECTION)
      glLoadIdentity()
      gluPerspective (60.0, self.width()/float(self.height()), 1.0, 10.0)
      glPopAttrib() # restore GL_MATRIX_MODE
     
  def paintTeapot(self):
      glPushAttrib(GL_POLYGON_BIT) # remember current GL_FRONT_FACE indictor
      glFrontFace(GL_CW) # teapot polygon vertex order is opposite to modern convention
      glColor3f(0.2,0.2,0.5) # paint it blue
      glutSolidTeapot(3.0) # thank you GLUT tool kit
      glPopAttrib() # restore GL_FRONT_FACE
 
 
class SphereTestApp(QApplication):
  "Simple application for testing OpenGL rendering"
  def __init__(self):
      QApplication.__init__(self, sys.argv)
      self.setApplicationName("SphereTest")
      self.mainWindow = QMainWindow()
      self.gl_widget = SphereTestGLWidget()
      self.mainWindow.setCentralWidget(self.gl_widget)
      self.mainWindow.resize(1024, 768)
      self.mainWindow.show()
      sys.exit(self.exec_()) # Start Qt main loop
 
 
if __name__ == "__main__":
  SphereTestApp()

2 comments:

Cătălin George Feștilă said...

I got this errors ... I think is something with override or decorators :
Traceback (most recent call last):
File "opengl_test.py", line 53, in paintGL
self.paintTeapot()
File "opengl_test.py", line 73, in paintTeapot
glutSolidTeapot(3.0) # thank you GLUT tool kit
File "C:\Python34\lib\site-packages\OpenGL\platform\baseplatform.py", line 407
, in __call__
self.__name__, self.__name__,
OpenGL.error.NullFunctionError: Attempt to call an undefined function glutSolidT
eapot, check for bool(glutSolidTeapot) before calling

Biospud said...

@Catalan George Festila: I think you might need to install GLUT on your computer to get around a problem like that. There is something called FreeGLUT that might do the trick. http://www.transmissionzero.co.uk/software/freeglut-devel/