To main page | 3dengine.org
Python CallList class
Python CallList class - a wrapper class to simplify
Call Lists usage in Python.
Call Lists are a way to draw static geometry very fast. (More than 1M points in real-time even in Python)
How to use it
cl = CallList(random_lines)
# replace random_lines with whatever YOUR function does the drawing
cl.draw()
cl.lazy_update()
while True: # OpenGL infinite loop
# clear screen here
cl.draw()
Obviously you
require OpenGL context, try my
python spectator code, but replace box drawing code with above call list ("fps.draw_simple_cube()" to "cl.draw()").
random_lines is the function that does the drawing.
What's that?
The idea is - generating 10000 random lines (or drawing a million points from database) takes A LOT of time in Python, but if you do it once and then call glCallList, then it's stunningly fast. Faster than C/C++ doing glBegin/glEnd each frame.
You supply a function (random_lines) and optionally it's arguments as second parameter ( cl=CallList(random_lines, (1,2,3)) )
You can mark calllist for update with either cl.lazy_update() or cl.update(). The lazy_update() can be called 1000 times for example, but will call update only once when the drawing will happen. The update() forces the update right this moment.
.lazy_update() is basically "next time when .draw() is called - call the function (random_lines) once and 'cache' the result";
When you call
.draw() first time does "lazy_update" first, so no need to explicitly call "lazy_update". You need to call "lazy_update" only when you need to update the "cached" geometry.
The update/lazy_update means that "random_lines" will be called again and the new result will be cached.
Actual Class
class CallList:
def __init__(self, fun = None, args = None):
self._id = glGenLists(1)
self._valid = False
self._update_fun = fun
self._update_args = args
def draw(self):
if self._valid:
glCallList(self._id)
else:
if self._update_fun is not None:
self.update()
def lazy_update(self):
self._valid = False
def update(self):
self.start(GL_COMPILE_AND_EXECUTE)
if self._update_args is not None:
self._update_fun(*self._update_args)
else:
self._update_fun()
self._valid = True
self.end()
def start(self, _call = GL_COMPILE):
glNewList(self._id, _call)
def end(self):
glEndList()
def __del__(self):
if glDeleteLists is not None: glDeleteLists(self._id,1)