Ingemar’s Little OBJ Loader

In 2005, I wrote the first version of a unit called LoadOBJ, to load OBJ models. It was very small, a 10k file that loaded OBJ in a rather clumsy way to a straight memory version of the same data.

A few years later, Mikael Kalms extended it significantly, with a linearizer to make it fit into modern the OpenGL model. This I think was when the capitalization was changed to loadobj. (Now it was 22k.) Jens Ogniewski made some more additions, and so did I. Now this little loader was 37k. However, it was not very capable and also not very readable. It failed on some files, and it did not support .mtl files for material definitions nor the multi-part splitting that is needed to handle them.

So, should I improve it or just switch to something better? Assimp? Too big for course material! The “tinyobjloader” sounds pretty right and it sure can do more than loadobj could. “Tiny” means a 70k file. But… it doesn’t quite do all I wanted, so I found myself sending the data it loads to loadobj!

Now, in 2019, I decided to make the much needed overhaul of loadobj. The duck below (source unknown, I thought it was from TurboSquid but I can’t find it) was my primary target, as a file that loadobj had a lot of problems with. The model is not textured, all colors are from a .mtl file specifying colors for each part; body, beak and eyes.

Skärmavbild 2019-11-06 kl. 21.35.26

This did take some work. I had already written the code to load a model split to several parts, but that code was buggy, and there were plenty of possible pitfalls in the OBJ format that I needed to address. Thus, this overhaul became pretty big! Not only did I find several weaknesses (now making it possible to load models with other problems than the duck) and added a .mtl parser, I also rewrote large parts, taking advantage of VectorUtils3 to simplify the OBJ loader and making it easier to understand.

The new version, including MTL support, is now renamed to LittleOBJLoader, LOL for short :). And it is down to a honorable 33k! (A bit bigger if you include vital parts of VectorUtils in order to make it stand-alone, quite a bit smaller if you cut comments.) This should be compared to 70k for tinyobjloader and 52k for the experimental “opt” version! With all respect to TOL, I hope LOL will be a useful OBJ loader in its own way.

The image above is rendered with LOL using its parsed material data for coloring each part separately. I have tested with a fairly extensive set of models, and most render correctly, including popular models like the dragon, Buddha, Sponza and the Sibenik Cathedral!

Important design choice: The loader splits over usemtl statements only. (There are a few other statements like “g” but I ignore those.) LoadModelSet will return a NULL-terminated array of Model structs, each containing a pointer to a material struct if that information was available. This means that drawing the array requires a for loop, in which you are expected to take whatever action appropriate to apply materials to shader variables.

Another design choice is that it is now dependent of VectorUtils, which makes much code more brief and easy to read. However, the dependencies are minor, so if you wish to adapt to another vector library, there are not that many changes to make as long as the library you use can speak C. You can also copy the few calls you need over to make the whole thing stand-alone.

How about a multi-part Utah Teapot? And being able to lift the lid procedurally? :) (This was done by adding a few usemtl lines in the teapot OBJ.)

During the path getting here, I saved some pictures of memorable buggy versions:

Frustrating intermediate results.

At this time, my demos ready for release are only using the kD part of the .mat files. I hope to provide a demo with textures at some time.


This page is maintained by Ingemar Ragnemalm.