mardi 6 mars 2012

Swig tutorial : gl2ps wrapper

Today I will explain you how to wrap a C file to call it from python.

I learned it by wrapping the C library from Christophe Geuzaine (http://geuz.org/gl2ps/) which allow you to export an OpenGL scene into a PostScript file (ps, eps, pdf or svg).
First you have to download and install a library called SWIG (http://www.swig.org/), if you are running on Ubuntu this can be easily done by taping the command line :

§ sudo apt-get install swig

Then you have to make a ".i" file to swig, which will be connected to the C header.
Start by opening a text editor and copy this :

%module gl2ps
%{
#include "gl2ps.h"
%}

%typemap(in) FILE* {
  $1 = (FILE *) PyFile_AsFile($input);
}


Here we indicate the future name of the module (gl2ps.py) and at which C header it will be linked.
Then you just have to copy all the necessary items from the header, in my case I copied all the lines starting from  /* Version number */ , I also removed if defined(_cplusplus) loops, endif /*__GL2PS_H__*/ statement and all the GL2PSDLL_API at the end of the header since I am on Ubuntu and will call this file from python. If you are running on Windows I think that you should past the entire file as it is but I haven't tried to swig on Windows so...
Once it is done just save the text file as gl2ps.i in the same folder than the header and C file. Then just run from the directory where all the files are :

§ swig -python gl2ps.i

This produce two files : gl2ps.py and gl2ps_wrap.c. After that you just have to create a little setup.py which uses distutils to help us compile the wrapped program. This tiny bit of code look like this (Note: to build this requires that OpenGL is currently installed in a common directory) :
from distutils.core import setup, Extension
setup(name="gl2ps",
      py_modules=["gl2ps"],
      ext_modules=[Extension("_gl2ps",
                             ["gl2ps.c","gl2ps_wrap.c"],
                             libraries=["GL"])]) 
That's it ! You just have to run...

§ python setup.py build or § python setup.py build install

...to begin to use your new gl2ps.py module (Note : if you are using it as standalone module in your application the _gl2ps.so file must be in the same folder than the gl2ps.py).

Example of use :
Just as a little key event in the pyglet graphics example.
@window.event
def on_key_press(symbol, modifiers):
    if symbol == key.S:
        print "let's test it !"
        state = GL2PS_OVERFLOW
        buffsize = 0
        fp = open("torus.eps", "wb")
        print "Writing... "
        while(state == GL2PS_OVERFLOW):
            buffsize += 1024*1024
            gl2psBeginPage("test", "gl2psTestSimple", None, GL2PS_EPS, GL2PS_SIMPLE_SORT,
                         GL2PS_DRAW_BACKGROUND | GL2PS_USE_CURRENT_VIEWPORT,
                         GL_RGBA, 0, None, 0, 0, 0, buffsize, fp, "torus.eps")
            batch.draw()
            state = gl2psEndPage()
        fp.close()
        print "Done!\n"
        return pyglet.event.EVENT_HANDLED

lundi 5 mars 2012

Python, pyglet, OpenGL and OpenCL

Hello,
I started this blog to talk about a new hobby of mine : programming.
As I had a bit of time for me this summer and I also just had learned how to use Matlab (mainly for image processing), I decided to extend this experience with some little OpenCV experiments. I started in C++ but was not completely happy with the compiling process so I decided to switch to python and give it a try... And I fell in love with it, it is a language that is actually really easy and fun to develop with. I made a little program that allow to control the mouse with the web-cam (color tracking, no clicks) and in august I started to use OpenGL, the result gave this blog its name :






 







It represents 1M particles moving inside a cube with a little collision detection algorithm to maintain them inside. It uses pyglet (http://www.pyglet.org/,
for windowing and also as OpenGL wrapper, I particularly like the "batch" feature, see for yourself !

The GUI is done with a tiny library called glydget by Nicolas P. Rougier (http://www.loria.fr/~rougier/coding/python) I really like the design but there are some extending to do, I would especially need a slider (someday I'll make one of mine...).

Particles movement and collision detection at the edge of the cube run on the GPU (graphic card) thanks to PyOpenCL (http://wiki.tiker.net/PyOpenCL). The OpenCL kernels derivate from the outstanding tutorial from Ian Johnnson (http://enja.org/category/tutorial/advcl/). The particles are in fact a points cloud with geometry shader. The resource from dlampletest was particularly useful (http://sites.google.com/site/dlampetest/python/vectorized-particle-system-and-geometry-shaders) as long as the pyglet glsl wrapper from swiftcoding (http://swiftcoder.wordpress.com/2008/12/19/simple-glsl-wrapper-for-pyglet/) to build the system.

I also implemented a FPS-type camera and a trackball that I derived from this tutorial (http://www.siteduzero.com/tutoriel-3-4978-controle-avance-de-la-camera-partie-1-2.html). This is a French tutorial but an English tutorial, from swiftless (http://www.swiftless.com/) or others should not be too difficult to find on Google).

It is implemented on my personal laptop (Ubuntu 11.10, Intel i5, Geforce GT 330M, python 2.7.2) and runs at ~15FPS, I tried to post a video of it but the result was too flickery.

I will not release the code as it is a rather old project that I already rebuild from byte codes using uncompyle2 (https://github.com/wibiti/uncompyle2), a little tool that I recommend when you, as I, have lost your files and want to recover them from byte codes (.pyc). I also think that I already provide an exhaustive list of better resources than mine that can be use to develop pretty fast the same program. But I will stay open to discuss it with you if you are interested.
This will be the only post on this project but I will post soon on my new project that I started last month which I called "Virtual Optics".