Monday, October 4, 2010

Inside Blender

Blender is made up of: 800 C files (.c), 1000 C header files (.h), 600 C++ files (.cpp), and 38 C++ header files (.hpp). Total lines of code about 1M.

SVN Check-Ins: (snapshot of source files, not total commits this year)
campbellbarton 1081
nexyon 156
blendix 75
gsrb3d 47
jesterking 31
broken 24
nazgul 20
dfelinto 20
aligorith 20

Inside The Blender C API: - Part 1



Diving into the source code you will find that the `main` function is in: blender/source/creator/creator.c
This mostly sets things up and calls the mainloop, which is actually WM_main found in: blender/source/blender/windowmanager/intern/wm.c
Blender uses the directory convention: `intern` and `extern`, which apparently defines which part of a library should be hidden or exposed to other libraries. Another convention (not always followed) is functions that begin with capital letters are exposed to other libraries.
WM_main only calls four functions in its while loop:
/* get events from ghost, handle window events, add to window queues */
wm_window_process_events(C);
/* per window, all events to the window, screen, area and region handlers */
wm_event_do_handlers(C);
/* events have left notes about changes, we handle and cache it */
wm_event_do_notifiers(C);
/* execute cached changes draw */
wm_draw_update(C);

These functions are defined in:
blender/source/blender/windowmanager/WM_types.h
blender/source/blender/windowmanager/wm_window.h
blender/source/blender/windowmanager/wm_event_system.h
blender/source/blender/windowmanager/wm_draw.h


Libblender - Getting Started:


Before trying the ctypes wrapper for libblender, you will need to compile blender as a shared library - on Windows this is a 'dll' file, and on Linux this is a 'so' file. First modify 'blender/CMakeLists.txt' and turn off both the game engine and python. Then edit 'blender/source/creator/CMakeLists.txt' and change:
ADD_EXECUTABLE(blender ${EXETYPE} ${EXESRC})
to:
ADD_LIBRARY(blender SHARED ${EXETYPE} ${EXESRC})
Finally, run cmake. If you have never used cmake to build blender, you need to create a new build directory outside of the blender source tree. On linux you would then run:
cmake -G "Unix Makefiles" ../blender
make


The lastest ctypes wrapper for libblender exposes enough of the C API to control the main loop. Converting the `main` and `WM_main` into ctypes looks like following:

import os, sys, time
from ctypes_libblender import *
from ctypes import *

def main():
_argv = ''
for arg in sys.argv: _argv += arg + ' '
argc = len(sys.argv)
argv = ctypes.pointer(ctypes.c_char_p(_argv))
C = CTX_create() # bContext pointer
BLI_threadapi_init()
RNA_init()
RE_engines_init()
pluginapi_force_ref();
init_nodesystem();
initglobals()
IMB_init()
syshandle = SYS_GetSystem()
GEN_init_messaging_system()
ba = BLI_argsInit(argc, argv)
setupArguments(C, ba, syshandle);
BLI_argsParse(ba, 1, None, None); # required, segfaults without this
sound_init_once();
init_def_material();
print ('WM_init...'); time.sleep(1)
WM_init(C, argc, argv); # some less random crash happening here
BLI_where_is_temp( c_char_p('/tmp'), 1 )
CTX_py_init_set(C, 1);
WM_keymap_init(C); # (this segfaults if BLI_where_is_temp is not called above)
time.sleep(1) # can segfault if we don't wait for the window to appear?
while True:
wm_window_process_events(C);
wm_event_do_handlers(C);
wm_event_do_notifiers(C);
wm_draw_update(C);

1 comment:

  1. Is it possible to extract Blender GUI library in separate library and use in own projects?

    ReplyDelete