Freestyle integration into Blender

May 29, 2008

Rendering step complete

Filed under: Update — The dev team @ 11:55 AM

I completed last post’s work by optimizing the rendering process (directly copying the back buffer into the RenderResult object instead of manually copying the information). I am sure that is a good performance improvement.

I also understood why the first render had its color inverted: I first noticed that the result was only showing the object silhouette, while it should have also shown the object (as it is selected by default in the viewer’s configuration). I then remembered that Stéphane had mentioned that the rendering process is made of two steps, building the strokes and rendering, and I then looked at what that “rendering” function could be. I came to understand that the Controller::DrawStrokes() method is the one responsible for building up the strokes, while the final result is obtained by the AppGLWidget::draw() method. Combining both methods resolved the issue.

Here is the corrected render result that should be obtained:

I am happy to note that from this revision on (rev 15047), we have a rendering foundation to base the remaining work on. Even though it is now limited to a static scene, I consider that the hardest challenges of the first phase have been resolved. I am also delighted that the project is on schedule and going forward. Getting tangible results is a big motivation boost and I am going to continue to bring the project further. Right now, I am going to slow down on the features and make sure that it compiles well on Linux and Windows. If all goes well, I should meet the June 8th deadline for finishing the first phase.

Other results:


  1. congrats.

    my own build dont show strokes. possibily something wrong with swig.
    i compiled with the datas in sconscript, but i probably missed something.

    i have following message in console : “Warning: current set empty”

    Also, it should be noted that you need to set render to render windows to get any result

    Comment by jean-luc — May 29, 2008 @ 12:34 PM

  2. Nice !! Is it me or the aspect ratio is not right? It’s not a big deal anyway because the way the strokes screen-space coordinates are currently computed is based on the window raster size (which is very bad), so we’ll have the opportunity to look a little closer at the projection matrix. In any case, congratulations for these first results, they’re good to see!

    Comment by stephane — May 29, 2008 @ 7:32 PM

  3. still no luck with the strokes. I tried various things with no changes, using both svn interface files and swig produced ones. I try to use the framework python

    I notice that swig produce slighty different output in :

    — source/blender/freestyle/python/ (revision 15049)
    +++ source/blender/freestyle/python/ (working copy)
    @@ -1,5 +1,5 @@
    # This file was automatically generated by SWIG (
    -# Version 1.3.33
    +# Version 1.3.35
    # Don’t modify this file, modify the SWIG interface instead.
    # This file is compatible with both classic and new-style classes.
    @@ -60,7 +60,7 @@
    __setattr__ = lambda self, name, value: _swig_setattr(self, PySwigIterator, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, PySwigIterator, name)
    – def __init__(self): raise AttributeError, “No constructor defined”
    + def __init__(self, *args, **kwargs): raise AttributeError, “No constructor defined”
    __repr__ = _swig_repr
    __swig_destroy__ = _Freestyle.delete_PySwigIterator
    __del__ = lambda self : None;
    @@ -674,6 +674,8 @@
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, Interface0D, name)
    __repr__ = _swig_repr
    + __swig_destroy__ = _Freestyle.delete_Interface0D
    + __del__ = lambda self : None;
    def getExactTypeName(*args): return _Freestyle.Interface0D_getExactTypeName(*args)
    def getX(*args): return _Freestyle.Interface0D_getX(*args)
    def getY(*args): return _Freestyle.Interface0D_getY(*args)
    @@ -694,8 +696,6 @@
    this = _Freestyle.new_Interface0D(*args)
    try: self.this.append(this)
    except: self.this = this
    – __swig_destroy__ = _Freestyle.delete_Interface0D
    – __del__ = lambda self : None;
    Interface0D_swigregister = _Freestyle.Interface0D_swigregister
    cvar = _Freestyle.cvar
    @@ -718,7 +718,7 @@
    __setattr__ = lambda self, name, value: _swig_setattr(self, Interface0DIteratorNested, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, Interface0DIteratorNested, name)
    – def __init__(self): raise AttributeError, “No constructor defined”
    + def __init__(self, *args, **kwargs): raise AttributeError, “No constructor defined”

    i’m a bit out of ideas here.
    Do you have env variables defined, or something not in svn ?

    Comment by jean-luc — May 30, 2008 @ 5:15 PM

  4. I just double-checked and I uploaded all the files in the source/blender/freestyle directory (except of course my own and the compiled Python modules). I do not use any particular environment variable (Freestyle uses the FREESTYLE_DIR by default, by I removed that dependency in app_blender/AppConfig.cpp and use the fixed directory variable TEST_ROOT_DIR specified in test_config.h).

    We’ll have to make sure that the different config paths (cf app_blender/AppConfig.h/cpp) are well instantiated. I’ll take a closer look today.

    Comment by maxime — May 31, 2008 @ 5:40 AM

  5. I tried compiling and linking with the local swig binary and environment and it seems to work (if I did not forget anything). Here are the steps I followed (I put the full path for clarity):

    export SWIG_LIB=/Users/mx/Documents/work/GSoC_2008/bf-blender/branches/soc-2008-mxcurioni/extern/freestyle/swig/Lib

    # verify swig library is recognized
    /Users/mx/Documents/work/GSoC_2008/bf-blender/branches/build/darwin/bin/swig -swiglib

    cd /Users/mx/Documents/work/GSoC_2008/bf-blender/branches/soc-2008-mxcurioni/source/blender/freestyle/intern/swig

    /Users/mx/Documents/work/GSoC_2008/bf-blender/branches/build/darwin/bin/swig -c++ -python -o ModuleWrapper.cpp Freestyle.i

    mv ./ ../../python/

    g++ -w -I../geometry -I../image -I../scene_graph -I../stroke -I../system -I../view_map -I../winged_edge -I/usr/include/python2.5 -I../../../blenlib -I../../../blenkernel -I../../../imbuf -I../../../makesdna -c ModuleWrapper.cpp -o ModuleWrapper.o

    # for Mac OS
    g++ -bundle -flat_namespace -undefined suppress -w -L/usr/lib/python2.5/config -L/Users/mx/Documents/work/GSoC_2008/bf-blender/branches/build/darwin/lib -lpython2.5 -lbf_freestyle -o ../../python/ ModuleWrapper.o

    Comment by maxime — May 31, 2008 @ 6:13 AM

  6. I think I may see a possible explanation to the “Warning: current set empty” message and the absence of strokes.
    The lines are not explicitly manipulated in the style module, instead they are stored as a state in the C++ library. Practically, in stroke/Operators.h, several containers are declared as static members of the Operators class (which also declares the select, chain, … operators as static methods). That is fine as long as the library that contains Operators is shared between the executable and the python extension. Now, with the current configuration, freestyle is statically linked to blender on one side and statically linked to the python extension on the other side (this last one is dynamically linked to blender). As a result, the freestyle code appears twice and the Operators containers also. So, I suspect that the set of initial edges (coming from the ViewMap computation) is initialized on one side but not on the side seen by the python extension which therefore believes that the set of edges is empty. What do you think?
    One thing that I don’t understand though, is why it works on your system :-S

    If that theory is confirmed, the solution would be to split the freestyle library into two or three sub-libraries, making sure that the library containing the states is linked only once into the blender executable.

    Comment by stephane — June 4, 2008 @ 6:57 PM

  7. Stephane thanks, your comment put me in the right direction and :


    compiling the wrapper must use the bundle_loader option :

    g++ -bundle -flat_namespace -undefined suppress -w -L../../../../../../build/darwin/lib -framework python -lbf_freestyle -o ../../python/ ModuleWrapper.o -bundle_loader ../../../../../../build/darwin/bin/

    It works on intels probably because they dont have flat namespace unlike PPC (I use a G5). but you still need to use the flag for bundle.

    I can now try to create the scons steps to do that automagically

    Comment by jean-luc — June 5, 2008 @ 3:31 PM

  8. This bundle_loader option is nice!
    I don’t know anything equivalent under windows though (?).
    I might be wrong but I think that the lib_freestyle still needs to be subdivided (or built as a shared library) for the symbol resolution to work on all platforms, no?

    Comment by stephane — June 5, 2008 @ 10:50 PM

  9. Stéphane, thanks for all the details. I only have a superficial understanding of Freestyle and I don’t think I would have been able to figure this out quickly.

    Jean-Luc, that’s great news. Send me the patch for this scons script as soon as you have it. That will allow us to test it on Linux and Windows.

    Comment by maxime — June 6, 2008 @ 7:30 AM

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: