Developers Guide


Editorial Note: This Document is in the process of being refined to support MakeHuman© V1.0 which is currently only available as a Apha1 Technical Preview.

Earlier versions of the software and the corresponding documentation are available from the MakeHuman web site .

Introduction

This document largely relates to the development of MakeHuman and contains information about installing the development environment and building a runtime version of the application. The average user doesn't need to read this document because, to run and use the MakeHuman application on supported Windows, Mac OS-X or Linux platforms you can simply download the appropriate installer for the currently released version. You can run the installer and use the application without needing to download or build the source or any of the development environment components described in this document. This document largely relates to the development of new features but also contains general build instructions that you may find useful if you are attempting to build a copy of the application to run on a platform that is not officially supported.

The home page for MakeHuman is at http://www.makehuman.org/ . The MakeHuman project is an open source project developed, managed and maintained by voluntary efforts. It is hosted on http://code.google.com/p/makehuman/ where the current source code is available for download from the SVN repository. An earlier CVS repository has been retained for reference purposes, but is no longer maintained.

This document is the 'Developers Guide' for the MakeHuman application and covers key aspects of the development environment configuration and setup on the various supported platforms (Windows, Mac OS X and GNU/Linux). It also contains the coding standards required to develop consistently high-quality code for the MakeHuman project and details key features of the Application Programming Interface that MakeHuman developers and Plugin developers can use to maintain and extend the product.

Application Overview

MakeHuman is constructed using two main application components:
  • The python interpreter that include an OpenGL 3D engine and forms the intentionally small core of the application is written in C.
  • The vast majority of the functional components, including the GUI and service functions are written in Python
Retaining this very small, highly optimised and stable C core avoids the need for pyopenGL and therefore avoids the need for Windows users to install the full Python package and to manually install a seris of extra packages with associated dependencies and consequent installation issues.

Although the majority of the development effort is focused on Python code (which is an interpreted language so doesn't require the application to be rebuilt for each code change), the C core does result in developers having to install the C development environment in order that they can perform a complete build.

The application is written in a layered fashion as detailed below.

This figure illustrates the two main components of the MakeHuman Application along with the integration layer that connects them. The Python code delivers MakeHuman Specific functionality. The C application provides a Python interpreter and exposes a set of generic MakeHuman functions through the integration layer. The integration layer consists of a set of C functions enabling events to be passed up to Python code and a dynamically generated Python module enabling C functions to be called from the Python code.

C code


The C language is a compiled programming language, requiring developers to install a development environment in order to be able to build changes to the C source code into the application. The C layer is intended to be relatively stable and provides generic functionality to the Python code, minimising the need for C development.
The 3D graphics environment as a whole, including most of the 3D mesh handling functionality is delivered using OpenGL calls embedded within the C application code. User interaction and user events are handled using the SDL (Simple Direct Media Layer) library within the C application code. The SDL library manages low-level events (e.g. Mouse clicks, Mouse Movements, Keystrokes etc.) and makes those events available to the application event loop.

C Data Structures

The principal data structures used by the C code are contained within the 'G.' global structure. This global data structure is defined in the file 'core.h' in the 'include' directory within SVN. Certain state information is held directly in 'G.', such as camera settings, viewport dimensions etc. Information required to define the 3D objects, such as the humanoid figure and the GUI controls is nested within the 'G.world.' data structure, which is a pointer to an array of object3D data structures. Each object3D data structure contains the information needed to define a single object to OpenGL (verts, norms, UV, colors etc.).
These data structures are detailed in the C code documentation at http://makehuman.sourceforge.net/C_Docs/  (Note: the number version 0.9.2 is wrong).

Python code


Python is an interpreted language which means that you can add functionality into the Python layer without needing to recompile or rebuild the application.
The MakeHuman application incorporates a complete Python interpreter enabling you to add Python functionality to the a released version of the application without having to install any development software. To add Python functionality to the version of MakeHuman currently under development you do need a development environment to build the application from source code stored in SVN.
MakeHuman functionality is delivered through a combination of core Python modules and plugin Python modules assigned as function attributes on a Python Scene3D object that is instantiated by the main Python module (main.py) at application startup. The application is event driven using the SDL library in the C core to detect registered user events. These events are passed up to the Python functions that have been registered to handle those events on the Scene3D object. The Python event handling functions can interact with the C core through the generic MakeHuman functions exposed through the integration layer to perform the required functionality before returning control to the application event loop to await the next event reported by SDL.

Python Data Structures

The data used to populate the C data structures is maintained through Python code and a copy of that data is held in Python data structures. Python application components load the 3D object data required to populate the corresponding C data structures from object files. That data is loaded into instances of Python classes, that are defined in the file 'module3d.py' (in the 'mh_core' directory in SVN) before being transposed and copied down into the C data structures. These classes can be seen as being organised in a sort of hierarchical structure; A single Scene3D object holds references to the set of Object3D objects used to describe the humanoid model and the various GUI controls. Each Object3D object contains lists of references to the FaceGroup, Face and Vert objects that are used to construct a single 3D object.
The data structures contained within these classes are detailed in the Python API documentation at http://makehuman.sourceforge.net/API/module3d-module.html .

Integration Layer

Specific low-level and high level functionality and events are exposed through a C/Python integration layer enabling high-level GUI operations to be delivered using interpreted Python code. The integration layer passes calls from the C code to the main Python module to handle events detected by the SDL module. These calls are made by functions in core.c which use the PyRun_SimpleString function to invoke Python functions. The integration layer also incorporates a series of C functions exposed through a Python class (named 'mh.') that is dynamically generated by main.c when the application starts. This class is created using the Py_InitModule function which registers a series of C functions as Python methods on the 'mh.' class. This provides a mechanism by which the various Python modules (called in response to an event), can interact with the generic functions and the global data structure in the C core.

Program entry

When the application starts, it starts by initializing all global variables. Then it prepares to call the main python entry, first setting the program name, initializing python, passing the program arguments and creating the makehuman python module.

When all that is done, main.py is called. This is done using

PyRun_SimpleString("execfile(\"main.py\")");

The reason this method is preferred instead of PyRun_SimpleFile is that the latter might crash on windows because of incompatible structures. Python 2.6 is compiled with Visual Studio 9, which filestructures are different from MinGW or Visual Studio 8.


Python entry

The main python script starts by loading the necessary modules, and creating the scene object. This object contains a list of the objects in the scene, as well as a dictionary mapping selection color to object. After the scene is created, the base mesh as well as the GUI meshes are loaded into the scene. At that point in time, all 3D geometry has been imported into the python runtime, but not yet into OpenGL.

Thus the next logical step is to copy the geometry to the C runtime which creates the necessary OpenGL vertex buffers (and textures?). Finally the event handlers are connected and the GUI is switched to modeling mode. At that point, the Python script calls startWindow which creates the window in the C runtime and starts the event loop.

SDL event loop

In most modern GUI's, an event loop takes control once everything is initialized. Our loop blocks on SDL_WaitEvent which waits for user input and/or timers. When an event occurs, it is translated and passed to the Python runtime. After handling the event, Python returns control to the event loop.

Redrawing is done by placing an expose event into the event queue. We don't just call draw directly because, if running on a slow system, the event queue would fill up and, after the user has finishes generating input events, a history of those events would be 'played' out. This is solved in two steps. Instead of calling draw directly, an expose event is posted in the event queue. This makes the drawing asynchronous just like the input events. This would still give the same problem, as many events would be posted, which can't be handled in time. To avoid this we mark that an expose event was put into the queue, and we don't place a new one in the queue until it is taken out of the queue and processed. This makes sense as we don't need to tell the system twice or more times to redraw, once an event is pending a redraw will occur eventually.

This way the system stays as responsive as possible, while drawing at the smoothest frame rate possible.

// The event loop
while not finished
    wait for event
    check event type
        input: pass to python
        expose: draw and clear pending flag
        custom: call python timer
        quit: finished

// The redraw method
if pending flag
    return
set pending flag
queue expose event

A similar strategy is used for timers. instead of calling the python callback directly from the SDL timer callback, we push a custom event into the queue and only if there isn't already one in the queue. This is done because the SDL timer callback is called from another thread, which might crash the Python runtime. Once the event loop finishes, the OpenGL textures are freed. And the event loop function returns. This brings control back to the Python runtime which finishes it's main script and returns as well.

Program Exit

Python is finalized and all object memory is freed.

The handler uses the dynamically created mh Python module to call mh_shutDown in main.c which in turn calls mhShutDown in glmodule.c. This issues a system exit(0) to end the application event loop. The exit performs a cleanup and control is passed back through the main function in the main.c file which issues a 'goodbye' message and exits.

Scene data

 A scene is stored as a flat object list, there is no hierarchy and thus no transformations or properties are inherited. This means that if a model wears clothes, the clothes need to undergo the same transform as the model, it is not automatic. Besides the object list, the scene also contains a dictionary of 'false' colors for each object, this enables the system to work out which object the user has clicked on by comparing it with an image generated from the current camera position using these false colors.

Object

Editorial Note: to update

An object is used to represent an object that can appear on the screen. This can be the humanoid object or one of the GUI objects. An object has a name to identify it in the scene. It also holds an index to the corresponding object in the array of C objects. For transformation it holds translation, rotation and scale settings and for the purposes of selection it holds a selection color. The object includes lists of vertices, faces and facegroups to enable it to be rendered. Other object properties which affect the rendering are cameraMode, visibility, texture, hasTexture and shadeless.

Facegroup

Editorial Note: to update
A face group represents a discrete, named group of faces within an object. The facegroup contains a name, a list of faces and the name of the object it belongs to.

Face

Editorial Note: to update
Each face represents an individual triangular face that goes to make up an object. A face has a list of 3 vertices (since it is always a triangle), a normal, its index in the list of faces, the name of the facegroup it belongs to, 3 vertex colors, a selection color and 3 uv coordinates.

Vertex

Editorial Note: to update
A vertex represents each vertex of each face of an object. A vertex contains coordinates, a normal, the index of the object this vertex belongs to, a list of indexes of faces and a list of faces which refer to this vertex, a list of corresponding C vertex indices, the index in the verts list of the object this vertex belongs to.

GUI system


Application

This is the main object in a certain application, it sets up the default categories and views, and loads the plugins.

Category

A category collects different tasks which work on similar aspects of the model, like modelling.

Task

A task makes it possible to work on a certain aspect of the model, or implements another function in the application like saving or loading.

Object

A 3d mesh which can be clicked on.

EventHandler

An EventHandler is a class which can receive events. Handlers for events can be attached to the EventHandler by defining the method in the class:
class MyClass(EventHandler):
    def onMyEvent(self, event):
        print("got onMyEvent")

However sometimes it can be bothersome to create a sub class each time you need different behavior in the handler. For this you can use the event decorator:

class MyParentClass:
    def __init__():
        self.myFirstClass = MyClass()
        
        @self.myFirstClass.event
        def onMyEvent(event):
            print("got onMyEvent in myFirstClass")

        self.mySecondClass = MyClass()

        @self.mySecondClass.event
        def onMyEvent(event):
            print("got onMyEvent in mySecondClass")

However note that using self here, will always give MyParentClass. If you need the self of the MyClass instance, use self.myFirstClass or self.mySecondClass in the handler.

View (EventHandler)

A view is a container holding other views and objects. When it is shown or hidden, all the views and objects it contains are shown or hidden as well (providing they are not individually hidden themselves). Views also have the notion of a focus. There is only one view which can have the focus at a time. The focussed view will receive all keyboard input.

Additional properties are:
  • parent: optional, defaults to None.
  • visible: optional, defaults to True.

Additional events are:
  • onShow/onHide: fired when the view's visibility changes.
  • onFocus/onBlur: fired when the view's focus status changes.

Widgets

Button (View)

A button is a standard push button. It has a selected state, which is only true when it is being pushed (between mouse down and mouse up).

Additional properties are:
  • selected: boolean indicating whether a button is showing itself as selected.
  • selectedTexture: a string indicating the optional texture to use when the button is selected.

Additional events are:
  • onSelected: fired when the button's selected status changes.

ToggleButton (Button)

A ToggleButton is a button which stays selected after you click it once, and deselects when you click it again.

Additional properties are:
  • none

RadioButton (Button)

A RadioButton is a button which can be put in a group. When one of the RadioButtons in a group is selected, all the others are deselected.

Additional properties are:
  • group: a list of RadioButtons which are exclusive.

Slider

A Slider is a widget allowing the user to select a value in a certain range.

Additional properties are:
  • backgroundTexture: a string indicating the texture to use as the background of the slider.
  • sliderTexture: a string indicating the texture to use as the slider of the slider.
  • value: optional current value, if not given defaults to 0.0.
  • min: optional minimum value, if not given defaults to 0.0.
  • max: optional maximum value, if not given defaults to 1.0.
Additional events are:
  • onChange: fired when the slider's value changes.

ProgressBar

A ProgressBar shows the progress of a lengthy operation. 

Additional properties are:
  • backgroundMesh: a string indicating the mesh to use as the background of the progressbar.
  • backgroundTexture: a string indicating the texture to use as the background of the progressbar.
  • backgroundPosition: position of the background
  • barMes : a string indicating the mesh to use as the bar of the progressbar.
  • barTexture: a string indicating the texture to use as the bar of the progressbar.
  • barPosition: position of the bar

Event flow

Mouse event

Application -> View under mouse

Remarks:
  • If left click, set focus if the view accepts focus.
  • MouseUp is only received after MouseDown
  • MouseDragged is between iMouseDown and MouseUp
  • MouseMoved is not between iMouseDown and MouseUp

Keyboard event

Application -> Focus View

OpenGL Notes

Most of the 3D mesh handling functionality is delivered using OpenGL embedded within the C application code. OpenGL is a 3D graphics library that enables a 3D world to be defined, with a camera, objects, lights, textures etc. It then enables that 3D world to be visualised as a 2D representation that can be displayed on a computer screen and provides functions to enable an application (in response to user input) to navigate around the scene.

Basics

OpenGL takes a 3D scene and draws it into a 2D viewing area on your screen known as the viewport.

OpenGL can project the scene onto the viewport in a variety of different ways, but the most common are:
  • Perspective projection, as you would get if you could place a camera in the scene
  • Orthographic projection, as a draftsman may contstruct technical drawings such as plans and elevations.

MakeHuman only uses Perspective projection.

Projection Transformation - You tell OpenGL how to project 3D objects onto the 2D viewport by defining a projection transformation, which indicates whether you wish to use perspective or orthographic projection (or an alternative projection pattern) and specifies other projection settings.

This can be imagined as being comparable to specifying the characteristics of a camera (field of view, aspect ratio etc.) where an orthographic projection is equivalent to a camera at an infinite distance. The main difference being that with OpenGL you can change the settings between drawing different objects, which is a bit like taking a photo, changing the lens and moving the camera, then taking another photo without winding the film on.

MakeHuman sets a perspective projection using the function gluPerspective(fovAngle,aspectRatio,near,far) where:
  • fovAngle: is the vertical field of view angle (45 degrees)
  • aspectRatio: is the viewport width divided by the viewport height which, by default, is 800/600 (4/3)
  • near: is the distance to the centre of the viewing plane (0.1)
  • far: is the distance to the centre of the rear clippling plane (100)

Modelview Transformation - For OpenGL to know what to display in the viewport it also needs to know where the camera is relative to the 3D model. For this you need to define a modelview which defines the position and orientation of the camera and the position and orientation of objects that go to make up the model inside a virtual 3D world. You do this by moving through and around the 3D world and by creating objects relative to your current position. OpenGL keeps track of your current position and orientation in the 3D world by recording the modelview transformation.

Both the projection transformation and the modelview transformation are stored internally in 4x4 transformation matrices. You can modify these matrices by calling functions that apply direct transformations (translations and rotations) or by calling functions that calculate transformations (e.g. the gluPerspective function outlined above). To apply transformations you need to first make one of these matrices the current matrix. Subsequent transformations are applied cumulatively to the current matrix. The glMatrixMode function is used to set the current matrix mode:
  • glMatrixMode(GL_PROJECTION) makes the projection transformation the current matrix so that projection settings can be applied, such as the Field of View angle and Aspect Ratio.
  • glMatrixMode(GL_MODELVIEW) makes the modelview transformation matrix the current matrix so that subsequent translations and rotations move the current location through the 3D world.

Resetting a transformation matrix

Matrix transformations that you apply are applied cumulatively. It is therefore often necessary to reset the matrix to its default 'no transformation' state so that you can apply a fresh set of transformations. OpenGL uses the transformation and modelview matrices to transform coordinates by performing a matrix multiplication. If you multiply by an identity matrix then the result is the same as the thing you started with, so to reset one of these matrices to an initial state where the transformation has no effect you can simply load the identity matrix using the function glLoadIdentity(). This loads the identity matrix into whichever transformation matrix is currently active, resetting it to the default 'no transformation' state.

Coordinates

OpenGL world space coordinates are unitless, so 2 units can represent milimeters, inches or light years. Interpretation of world space coordinates is up to the application. OpenGL uses a right handed coordinate system, so, if you are looking at the origin with the +X axis stretching away to the right and the +Y axis pointing straight up, the +Z axis will be heading out of the screen straight towards you and the -Z axis will be dissapearing away from you into the distance.

MakeHuman uses the default OpenGL modelview camera settings which are equivalent to invoking gluLookAt(0,0,0, 0,0,-1, 0,1,0). This places the camera at the origin, looking straight into the model along the -Z axis with the +Y axis pointing straight up. This means that a 2 unit wide and 2 unit high object centred at <0,0,-1> will roughly fill the viewport, as will a 4x4 object at twice the distance from the viewpoint.

Drawing objects

MakeHuman contains multiple objects. The Humanoid object is the main object, but it is surrounded by a set of control objects. Each object is constructed using triangular faces. The position and orientation of each face is defined relative to the object of which it is a part. The positions and orientations of the vertices and normals of the faces are defined relative to the face they're on. The sequence in which face vertices are defined is significant in OpenGL. If the face is viewed from the front, the sequence of points runs counter clockwise. If the face is viewed from the back the points run clockwise. Faces viewed from behind may be invisible or may have a different color/texture defined to the front face.
The glPushMatrix and glPopMatrix functions can be used to store away a copy of a matrix that can subsequently restored. MakeHuman uses this before and after drawing each object to store a copy of the modelview matrix and restore it.

The C Development Environment

A development environment enables you to compile and build a new copy of MakeHuman from source code held in the MakeHuman code repository. To simply run the MakeHuman application on Windows, Mac OS-X or Linux, you should not need a development environment as you can usually just use the current released version, which comes with an installer for your operating system. The released software incorporates a Python interpreter, so plugin developers can write, test and use Python scripts without necessarily requiring a separate Python development environment (see the Plugin Development section of this guide).

You do need a development environment to:
  • Participate in the development of the MakeHuman
  • Build a copy of the application currently under development
  • Build a copy of the application to run on a platform that is not officially supported.
To participate in the development of the MakeHuman code as a MakeHuman Team member you will also need to familiarise yourself with the Coding standard and Build Processes contained within this document.  The 'C' compiler is platform dependent. The following are recommended for MakeHuman development:

Windows 'C' Development Environment

The supported environments for MakeHuman 'C' code development are MinGW and Microsoft Visual C++
  • To roughly build MakeHuman, you can simply run the compile_src.bat file (maybe you need to adjust it, in order to match your local paths).
  • A better result is obtained using Visual C++ (see section Mingw vs. Visual C. below). Actually there is not a VC project file in svn, but it will be added before the release 1.0 final.

Windows Visual C++ 

  • Python 2.6 (headers + python26.lib + python26.dll)
  • SDL 1.2.13 (headers + SDLmain.lib + SDL.lib + SDL.dll)
  • SDL_Image 1.2.7 (headers + SDL_Image.dll + optionally jpeg.dll, libpng12-0.dll, libtiff-3.dll, zlib1.dll)

Windows gcc

  • Python 2.6 (headers + libpython26.a + python26.dll)
  • SDL 1.2.13 (headers + libSDLmain.a + libSDL.dll.a + SDL.dll)
  • SDL_Image 1.2.7 (headers + SDL_Image.dll + optionally jpeg.dll, libpng12-0.dll, libtiff-3.dll, zlib1.dll)
The MakeHuman application uses functions from the SDL_image libraries which needs to be linked into the program during the build. You will need to place the set of associated DLL's in a directory accessible during the build.
The DLL files are available for different platforms from http://www.libsdl.org/projects/SDL_image/release/. For example, a zip archive is available for Windows called : http://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.7-win32.zip. Just copy all of the DLL's from the archive into a directory in your build path before you build the MakeHuman application.

MinGW vs Windows Visual C++ 

An SDL program needs to be linked to a static library called SDLmain, which provides the main/WinMain entry of your program. The original main entry is renamed using a #define when including SDL. The visual C++ version of this SDLMain called SDLmain.lib is compiled using --disable-stdio-redirect while the MinGW version called libSDLmain.a seems to be compiled without this flag. This makes the MinGW version redirect all output to two files, stdout.txt and stderr.txt. Python doesn't like this, and output from python will fail in this case. A workaround is to redirect Python's output itself to file before it does any output:

f=open("outFile.txt", "w")
sys.stdout = f

.. .. 

f.close()


Adding this redirection is implemented in main.c, only when building on windows with gcc:

#if defined(__GNUC__) && defined(__WIN32__)
    err = PyRun_SimpleString("import sys\nf = open(\"outFile.txt\", \"w\")\nsys.stdout = f\nexecfile(\"main.py\")\nf.close()");
#else
    err = PyRun_SimpleString("execfile(\"main.py\")");
#endif


The real cause why Python fails is still to be examined.
Another workaround is rebuilding SDL for MinGW using the --disable-stdio-redirect flag.

Linux 'C' Development Environment


Linux gcc

  • Python 2.5 (headers + libpython2.5.a)
  • SDL 1.2.13 (headers + libSDLmain.a + libSDL.a + libSDL.so)
  • SDL_Image 1.2.7 (headers + libSDL_image-1.2.so.0)
Using Ubuntu or Debian, this mean you need to install, by synaptics, the following packages:
  • build-essential
  • python2.5-dev
  • libsdl1.2-dev
  • libsdl-image1.2
  • scons
The compiler (of course, GCC) is included in build-essential package.
Compile under Linux is very simple. If you have all packages listed above correctly installed, you must just open the console, go in MH folder and type "scons".

SCons is a Python-based cross-platform build environment that can be used to simplify the build processes for cross-platform applications. Knowledge required to successfully build the application can be built into SCon scripts, which can validate the environment and provide user-friendly information to the person performing the build in the event that the environment is incomplete. A draft SConstruct build script is provided in the current MakeHuman SVN build directory, although at the time of writing it is likely still to need adapting for your particular platform. is an useful utility (http://www.scons.org/ ) and in future we will use it for Windows too.


Mac OS-X 'C' Development Environment (To be updated)

The Project source files stored under SVN contain an Xcode project that is currently out of date. Until a new project file is available MakeHuman needs to be built using a 'make' shell command. SVN also includes files needed to adapt the 'C' source code for Mac OS-X builds.
Whether using an Xcode project or the 'make' shell command to build MakeHuman you will need to install the Xcode Tools which include the GCC C Compiler. Xcode is not installed by default, but is part of the "OS-X Developer Tools" package which is available on your OS-X installation DVD. If you don't have the DVD you may download an image of this DVD free of charge from the Apple developer site at http://developer.apple.com.

Currently the build process uses a 'make' shell command which is unusual for OS-X. OS-X build processes usually use the 'Xcode' development system which provides a fully Integrated Development Environment (IDE) that incorporates editors, a build system, dependency generation, debugging support etc. An Xcode project file for the current source deck is under development. For further information about the Xcode Tools please refer to http://developer.apple.com/tools/xcode/ . The standard OS-X build process uses an Xcode project to build the source downloaded from SVN. You have two choices to compile the source deck that you download from SVN:

  • Either you may use a makefile to perform the build. You can use the file ' compile_src_osx.sh' which is used to launch a 'make' command specifying the 'Makefile_osx' file as the parameter file. ie 'make -f Makefile_osx'. This command compiles and builds the C core.
  • You may load the Xcode project file named MakeHuman.xcodeproj into the Xcode Development IDE and perform the build within the Development system.
Both ways assumes that you have already installed the free Xcode package which incorporates a C/C++, and Objective-C++ compiler.

NOTE: Since the latest version of MakeHuman uses Python 2.5 or above, MakeHuman will run only on Mac OS X Version 10.5. or above because prior versions will be shipped with older versions of Python and not work!

If you are using a different Interactive Development Environment (IDE) then you will need to use a text editor to adjust the makefile parameter file before launching the shell script.
In Addition the build system will use some custom Open Source Frameworks which are not maintained by the MakeHuman team. However the SVN contains these Frameworks so you don't have to bother to explicit download them.

The Python Development Environment

The vast majority of the functionality delivered by MakeHuman is written in Python which has been used to develop GUI components, service functions and even certain processor intensive functions, such as subdivision. The rationale for developing in Python is that it results in highly human readable code, it is largely free of 'silent crashes', it is easier to find coders to contribute to the development and is far easier to debug than 'C'. The price we have to pay is with the performance of some processor intensive algorithms.

The MakeHuman application incorporates a Python interpreter enabling Python plugins to be developed against a released version of the MakeHuman application without the need for a separate Python Development Environment. This Python interpreter is link-edited into the application whenever the 'C' code is compiled/built, so in order to compile and build the MakeHuman application you will need a Python Development Environment installed on your machine.

Once built, you will be able to run and test any changes made to Python code without having to rebuild the MakeHuman application. You'll simply need to restart the application to pick up your Python changes. However, to incorporate any changes to the 'C' code made by you or by other developers and downloaded by you from the SVN repository you will need to recompile and rebuild the MakeHuman application.

Python is available free from http://www.python.org/) . The Python installer is about 10MB. The installed Python interpreter occupies about 60MB of disk space.

To participate in the development of the MakeHuman code as a MakeHuman Team member you will also need to familiarise yourself with the coding standards and build processes contained within this document


Obtain MakeHuman Source

Anyone can get a copy of the MakeHuman source deck by pointing an SVN client application at the repository.

SubVersion (SVN) Client

To be able to participate fully as a MakeHuman developer you will need an SVN client application. This will enable you to take a local copy of the MakeHuman files, regularly update your local copy from the SVN repository and (if you are member of MHteam) commit changes that you have made (and properly tested) back to the SVN repository. SVN update permissions are controlled by the MakeHuman development team, so you'll need an administrator to authorise you with write access.

Different subversion client applications are available for different Operating Systems, many of which are free to use. They each work in slightly different ways, but the differences are relatively minor. See http://subversion.tigris.org/ for a list of Third party SVN client applications.

For example, the Tortoise client for Windows acts as a Windows shell. Once installed it adds SVN client options to the popup menu that is displayed whenever you right click a file or a sub-directory in the Windows file explorer. To obtain a new copy of the MakeHuman SVN development directory structure you select the 'SVN Checkout' option from the explorer menu and enter the URL of the MakeHuman SVN repository.
Other SVN clients provide a comparable mechanism for checking out a copy of the SVN directory structure and will also require the URL:

http://makehuman.googlecode.com/svn/trunk/


Coding Style

Python

Python code must be written following the rules of PEP 8 and PEP 12.

Do not write Python getters and setters unless you can prove that you need something more than simple attribute access. Instead read http://dirtsimple.org/2004/12/python-is-not-java.html and use the 'built-in' property.
Getters and setters waste CPU time, but more important, they waste programmer time for those writing, testing and reading the code.

C

C code must be formatted using Astyle software, from http://astyle.sourceforge.net/ (ANSI style).


Coding Rules

  • Indenting (astyle options for C).
  • Follow the established MakeHuman naming conventions.
  • Add clear and concise comments to your code. Explain what the code does in real-world terms, don't just paraphrase the code.
  • Add information that can be read by the current automated API document generation utilities (see the Documentation section of this guide).

The openGL core is entirely contained within the file glmodule.c and ad heres to the following rules:
  • "only-what-is-absolutely-needed" is coded in C
  • pointers are avoided where at all possible
  • complex patterns are avoided
  • the C coding is kept stylistically as simple and readable as possible

SVN usage

  • Test all changes before submitting to the repository. As an absolute minimum make sure your changes won't break the build for other developers.
  • Commit changes as soon as possible so that other developers aren't developing against out of date code.
  • Ask for permission before writing into another persons repository. SVN write permission doesn't give you the right to write without bounds!
  • Only insert files in SVN that aren't available through another place. EDITORIAL NOTE: This needs clarification

Bugreports

Where to report bugs?:
Check existing bug reports before submitting your own to avoid duplication. If you have additional information add a comment. EDITORIAL NOTE: Check SVN supports this.
Bug reports should specify:
  • The Operating System or systems affected, or at least the OS upon which the bug was observed.
  • MakeHuman version information, including whether it is a pre-built or self-built installation.
  • Precise and concise information about which modules, methods, classes etc. are involved if this is known. If you think it's down to a certain module, say so, but also say if you're not sure.
  • If the bug is in a build of code that is under development, indicate the date that you downloaded it.
  • If you suspect your bug is related to an existing bug report or reports, say so and indicate which ones.



Plugin Development

Editorial note: to update
The MakeHuman application is an Open Source application that has been structured to encourage the development of plugin applications using the Python programming language. The application incorporates a Python interpreter which enables developers to write Python scripts for MakeHuman without needing to install a development environment. This document assumes that plugin developers already have a reasonable understanding of general application development concepts and of the Python programming language.

Introduction

This section of the document describes how to go about developing a MakeHuman plugin. The specific approach required will clearly vary depending upon the purpose and design of the plugin you wish to create, so this text is structured to attempt to help you to categorise the type of plugin and assess the type of development that you will need to undertake to develop your plugin.

MakeHuman functionality is largely implemented in the Python programming language, but relies upon a small and efficient C application that provides generic core functions. Plugin developers should familiarise themselves with the Application Overview section of this Developers Guide, which describes the relationship between these two language components and explains the general design of the MakeHuman application.

It is anticipated that most of the work involved in developing plugins will be in coding Python scripts. However, it is foreseen that some changes to the central C code could be required from time to time to add support for functionality required to develop certain specific types of plugin. It should be noted that such changes to the C core will need to be performed in collaboration and consultation with the MakeHuman team to ensure that they do not adversely affect core functions, performance, reliability or cross-platform compatibility. For changes to the core C application you will need to install a full development environment (see the Development Environment section of this guide).


Existing Plugins

Each of the different application modes, along with the export and rendering functions to integrate with different renderers are coded as plugins and can serve as an example to plugin developers to illustrate how extra plugins can be implemented.


Python Interpreter

The MakeHuman application incorporates a Python interpreter which can be used to invoke a plugin. The MakeHuman Python interpreter provides the plugin with access to the Application Programming Interface exposed by the MakeHuman application. If you write a Python script called 'foo.py' you can invoke it with the command "makehuman foo.py".



Plugin Categories

It is anticipated that future development will include conversion utilities to integrate with an extended range of modeller and rendering applications, feature enhancements, such as animation features, clothing, hair and prop integration and tools/utilities.

There are plugins under development for extended characters based upon alternative meshes, for example a 'toon' mesh for cartoon-like characters with exagerated features. It is also possible to envisage plugins to support the modelling of other types of creature.

The following list cannot be comprehensive, but is provided as a guide to help you categorise the type of plugin you intend to develop.

Export/Import format converters

These can generally be built using the classes, functions and data structures provided by the MakeHuman API documentation at http://makehuman.sourceforge.net/API/ . Python source for the Renderman and POV-Ray export functions is already provided in the plugin directory and can be used as an example.

When designing a converter you will need to have a reasonable understanding of the model format that you wish to develop and the features that you plan to support. The humanoid mesh should be fairly straight-forward to convert. An instance of the Object3D class contains the humanoid object with references to the Vert objects which store vertex data and the Face objects that point to the 3 Vert objects used to define each face. You are also likely to need information about the surface normals and potentialy UV-Mapping data if you plan to support uv-mapping of texture maps. Each face of the model is assigned to a face group. See the section Full API in this document for the URLs of the various pages used to document these face groups.

Developer Tools and Utilities

In this context the term tools and utilities is used to refer to things like the Morph Target Generator that is incorporated into the MakeHuman application, but which is only expected to be used as a utility to enhance the MakeHuman application and not something that is used by the average user.

Feature enhancements

The MakeHuman application currently supports the modelling and posing of humanoid characters, but it does not yet support many of the features that users will need such as hair, clothing and other props, animation etc. It is anticipated that most such enhancements can be coded using Python without requiring changes to the C code. An example of some of the things that could fall into this category include:
  • Finger Nail color picker
  • Animation controls
  • Hair
  • Clothes
  • Shoes
  • Prop
  • Text to Speech Generators
  • ...

Other models and model types

The MakeHuman humanoid model uses a single base mesh with mesh deformations being applied using morph targets that map specifically to this one mesh.
However, the application code works in a highly generic way and could potentially be used with alternative base meshes. For example, the same application code could be used to manipulate a quadraped if an appropriate base mesh and corresponding morph targets were developed:
  • Toons
  • Aliens
  • Quadrapeds
  • Birds
  • ...


Consistency

It may also make sense to develop specific plugins/application functions that can be used by multiple plugins. For example, it would be messy for someone to develop a finger nail color picker that worked differently to a color picker for hair color or lipstick. Also, list boxes and data entry panels should all function in a consistent manner, otherwise users will need to re-learn the basics of the interface for each plugin.



SVN quick intro