Isaac Newton wrote to Nathaniel Hawes on 25 May 1694.
Sunday, September 26, 2010
"A Vulgar Mechanick can practice what he has been taught or seen done, but if he is in error, he knows not how to find it out and correct it; . . . Whereas he that is able to reason nimbly and judiciously about figure, force, and motion, is never at rest till he gets over every rub"
Sunday, September 5, 2010
I just released a small viewer for the Biovision BVH mocap file format.
It can be downloaded from this page: http://jadnohra.net/?page_id=58
I did not plan to write this viewer, but I suddenly found myself having all the code I need for it while writing code for my animation research projects.
The 'Bigeye' UI library
I already had developed the 'Bigeye' UI library. This was I think the 4th UI library I had ever written. For this one, I had a couple of goals in mind: Small, OpenGL based but without state management headaches, easy integration of 3D scenes using render to texture, good looking with shadows, mouse-over, gradients, ttf and svg, no complex auto-layout/resizing support, no need for editor or text definition (at least not for the first versions). It took a number of weeks for this to happen, but I am very pleased with the results.
A key idea was to use the ImageMagick library which is basically, photoshop/gimp in your code.
It allowed me to create nice and detailed widgets without having to prerender them in an image editor.
Compiling and linking ImageMagick can be quite a headache, but after that is done, using it is a lot of fun. I spent quite some time reading 'how to make a nice button' tutorials and trying things out in gimp before deciding on a look, one of the main inspirations was the Zbrush user interface. Colorpic was also a useful ally in debugging the looks and colors of various widget screenshots that I wanted to reproduce.
For the UI I wanted to keep things simple, but still self managing, I went for a render tree approach, with automatic dependency management which was important for the 3D scenes rendered to textures. That way, RenderToTexture widgets could simply declare their dependency on a different (3D) RenderTree than their current tree (the main UI tree), and the Renderer would automatically take care of ordering the trees. Inside a tree, parents would render before their children.
The rendering would happen in three stages, building the render tree, figuring out dependencies, and then rendering in the right order.
For render states, again a simple design with one hashed state containing all the options needed for all the UI widgets (e.g: enabling transparency, texture, etc...). Each UI element would set it's desired render state instance, and the rest would happen automatically. Of course this is not the most flexible or performant design as code needs to be added to the render state structure and it can grow big, and for options that are not in the render state (e.g: line width) care must be taken to set them every time they are needed, but for a tiny UI like this, it does the job perfectly.
Biovision .BVH file format
Of all mocap formats, .BVH is the simplest, but many free mocap resources in bvh format exist on the internet, specially the .BVH conversion of the CMU mocap database is great. I will probably add .c3d support when I feel need it.
The format is relatively well documented on the internet. The fact that it uses Euler angles is usually the biggest source of headaches as I gathered from forums. I also had to try a couple of things out before finding out what the right way is. This included looking a the blender importer source code and even having fun writing a feature-incomplete bvh exporter for blender. A precise answer to the question of how to create a rotation matrix from the angles is nowhere to be found, because of that even some bvh viewers (bioviewer) got it wrong.
BVH euler rotation order
According to this very helpful resource: http://www.cs.wisc.edu/graphics/Courses/cs-838-1999/Jeff/BVH.html
one way to build the rotation matrix is to concatenate the matrices built from each angle in the order Y,X,Z. This is not entirely correct. The order should follow the one delcared in the bvh file itself, this means that if in the bvh file you see: "CHANNELS 3 Zrotation Xrotation Yrotation"
you concatenate with the order Y,X,Z but "CHANNELS 3 Xrotation Zrotation Yrotation" would require the order: Y,Z,X.
Since most files use the Y,X,Z order this bug can easily slip by.
Some of the CMU mocap files have a different order and look wrong in the viewers that got it wrong.
Of course, as usual, care must be taken about the coordinate systems and the order of matrix multiplications. Depending on you code, this might be different.
In a previous project of mine, I had a very elaborate runtime coordinate system conversion system, but this time I kept it simple and convert everything to an OpenGL compatible system when loading.
Everybody hates dependencies, but if you want to be productive, and pick the right ones, it is not so bad. In the past I avoided them like the plague, which was very educational, but this time around I am using the glm library (basically glsl on your pc) for math, strtk for strings (a great library which makes file parsing a ride in the park), glew for OpenGl extensions (which I need for rendering to texures using FBO), OpenGLUT and finally ImageMagick. I link all of them statically except for glew for now.
The viewer loads bvh files using drag and drop and has the usual playback controls.
It analyzes the scale of the skeleton and the bounding box of the animation space, from that it decides on the best grid size, depth planes, camera position and camera movement speeds.
I implemented a simple 'turn table' camera controller (as inspired by Blender).
I also copied the way Blender renders Skeletons, without lighting for now.
If you download it and like it, let me know.
If you have any feature requests, let me know as well...
Labels: bvh mocap viewer animation