Recently got my Wavefront OBJ parser to a much more usable state. There are two APIs you can use: (1) A low level API where you provide your own parsing memory buffer, error callbacks, loaded file contents and where you manually load in MTL files, and (2) A high level API, which basically does all of that for you using the CRT, and automatically loads MTL files (less shippable, but nice for getting something working quickly). The parser will spit out a list of renderables, which correspond one-to-one with the materials in the OBJ file, so you can directly pipe those to your renderer as renderable model subsets. It will also merge renderables with the same material. Currently, vertex buffers are interleaved, just XYZUVNNN (position, UV, then normals); let me know if you want API support for other output formats. Adding in other formats should be pretty easy to do.
The low level API does not allocate any memory, so you don't need to call any freeing functions if you provide your own parsing memory.
Here's the parser: https://gist.github.com/ryanfleury/0062f2ffdec07bcda8a4a0ef5c7f8f37. It's a single file, and you use it STB-style, e.g. with
#define OBJ_PARSE_IMPLEMENTATION then
Here's Sponza with all materials loaded in!