Monthly Archives: February 2013

Thinking outside the Box2D

When one thinks of the capabilities of Box2D one instantly conjures up images of flying birds, angry flying birds. So what really lies underneath the hood of this little engine that could. Well there’s only one way to find out. So I grabbed myself a copy of the latest code, version 2.12 as of this writing. The first thing you need to do after downloading is configure it with cmake to generate the visual studio solution and associated projects. Which is not to difficult just a matter of unzipping the source somewhere, pointing cmake to that directory, set a build output directory, hit the configure and if no errors hitting generate. A solution called Box2D should be created, open it and build both a debug and release build and you’re good to go.

To assist in getting up to speed with Box2D, there is the usual hello world program. This does nothing more than track the movement of a Box2D object or body (as it is defined) and output it to standard output. Better examples are contained within the folder named Testbed. Inside there is a program that when run allows you to choose a set of examples configured to display and render graphically using OpenGL, freeglut and glui. More importantly all the code is available soone can see how it is all done. Its cleverly designed in a such way to be easily extensible. Just create another header file defining your world, body and fixtures while also including the usual Step, Create and Keyboard functionality and add a new entry into the testentries code file and your done.

As with all frameworks there are certain workflows a developer must abide by to create and use the API correctly. In Box2D, you need to define a world in the form of a b2World object. Think of this as your standard factory pattern that allows you to create other things. Within this world, the other things that can be created are bodies, fixtures and shapes. You can create the world object using new, however due to how the memory is contained in pools you can not new bodies, fixtures and shapes. So dont do it. One of the first things I found out about Box2D is it is renderer agnostic, it basically lives as an entity that you tell to work in a world and how you wish to display that world is up to you. What is strange though for an API designed in C++, why are there so many examples found on the web all using mainly Flash. My knowledge of Flash is dismal to non-existent so you can imagine for a beginner you have this API that can create worlds and there are no examples of how to display your beautiful world. In the end I decided to traverse the testbed example and break it up into the minimum functionality that would produce an output.

Here in lies one of the first hiccups I had using Box2D, evidently it was not triggered by Box2D itself rather it was freeglut. I created a new empty console project and added the necessary files from the testbed, namely Test, Render and Main. I linked the freeglut_static.lib file and all was good except when it came time to run, it complained that freeglut.lib was missing. I thought this was strange as I had linked the static lib. Searching through some forums, I sourced a reputable prebuilt lib file and used it, it fixed the issue provided I also placed the associated freeglut.dll in the executable directory. The program fired up with no popups and then instantly terminated, flashing an error message in the command window before shutting down. After tracing through the code I discover the message was trying to say:

freeglut function called without first calling ‘glutinit’

int main(int argc, char** argv)
{
testCount = 0;
while (g_testEntries[testCount].createFcn != NULL)
{
++testCount;
}

testIndex = b2Clamp(testIndex, 0, testCount-1);
testSelection = testIndex;

entry = g_testEntries + testIndex;
test = entry->createFcn();

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(width, height);
char title[32];
sprintf(title, "Box2D Version %d.%d.%d", b2_version.major, b2_version.minor, b2_version.revision);
mainWindow = glutCreateWindow(title);

glutDisplayFunc(SimulationLoop);
GLUI_Master.set_glutReshapeFunc(Resize);
GLUI_Master.set_glutKeyboardFunc(Keyboard);
GLUI_Master.set_glutSpecialFunc(KeyboardSpecial);
GLUI_Master.set_glutMouseFunc(Mouse);
...
}

As seen in the highlighted code snippet above, I had actually called glutInit so what could possibly be causing the issue. After debugging I could see that line that was causing the issue was the call to GLUI_Master.set_glutReshapeFunc(Resize);. Now GLUI_Master is a global instance that should be available with the initialisation of glut, so if I was calling glutInit… why then wasn’t this being intialised as well. Several hours past I finally found it to be due to the mixing of the freeglut_static.lib and freglut.lib. The fix was as simple as adding the preprocessor definition FREEGLUT_STATIC. Once in place all the code I transferred from the testbed program into my solution worked. So with a working testbed and seeing exactly how everything hooked up, what else could I do. I decided that perhaps putting together an angry birds clone would fuel my persistence to learn Box2D in more depth. At this stage I only feel like mimicking the first level with the aim to make it as close as possible to the original in functionality.