LibX

Development

I implemented LibX together with my friend Basil Fierz during our free time in spring 2007.

Detailed Description

One of the problems every hobby game developer faces is the fact that he/she has to create and load artistic assets (3d models, audio data, textures, etc.). For a good asset pipeline (consisting of art creation, post processing, data optimization and import) there is a huge amount of implementation work to be done. I designed LibX to solve one piece of the puzzle, the handling of the Microsoft .x 3d model format. It has most of the features expected from a modern 3d file format, such as skinning and animation. The format is also designed to be extendible if there is a feature missing. LibX consists of three parts:

The most important part of LibX is the so called LibX core. The core consists of a set of classes used to read and parse .x files. One could compare the LibX core to an XML DOM parser. It just reads the data, either from a text- or a binary file, and stores them inside an object structure. It neither transforms nor interprets the data read. An engine could then take the model object structure and convert it into its own internal data structures.

Such a model object structure can contain elements (like polygons with an arbitrary number of vertices) that are not suitable for rendering using a graphics card. LibX model is built on top of LibX core to handle those details. It implements a 3d triangle mesh structure that can be used for rendering purposes and converts the model object structure from LibX core into it.

The third and last component of LibX is the LibX viewer. This component is used for demonstration purposes. It takes the 3d triangle mesh generated by LibX model and visualizes it using OpenGL. This component has been written by Basil Fierz.

Technical Details

Feature List

Challenges

Clearly the main challenge with writing this library was the poor documentation of the .x file format. Even though the DirectX SDK contains a complete description of the format it is very short and spread over different non-intuitive documentation pages. Also the library has to be tolerant regarding the input file since there are different exporters that may interpret Microsoft's .x documentation in a different way than LibX. So we had to collect documentation and .x files from different sources to get things right. In the end we managed to display files, where the built-in DirectX .x file viewer did not display correct results but there might still be lots of compatibility issues.

Screenshots

Videos

Code Sample

This code samples shows the main loop where LibX core parses and reads a .x file.

//------------------------------------------------------------------------------ /*! \brief Datei auslesen \param info Alle Templates und alle Template-instanzen auslesen. Die gelesenen Informationen werden in 'info' hierarchisch zwischengespeichert. */ void Serializer::ReadFile( TemporalInfo& info ) { if (info.header.IsText()) { info.mode = TemporalInfo::FileModeText; info.scanner = new TextScanner(); } else if (info.header.IsBinary()) { info.mode = TemporalInfo::FileModeBinary; info.scanner = new BinaryScanner(); } else if (info.header.IsTextCompressed()) { throw NotSupportedException( UNICODE_STRING("compressed-text-format-reader todo!") ); } else if (info.header.IsBinaryCompressed()) { throw NotSupportedException( UNICODE_STRING("compressed-binary-format-reader todo!") ); } while (!info.scanner->Eof(info)) { Token* token = info.scanner->ReadToken(info); if (token == NULL) break; switch (token->GetType()) { case Token::TypeTemplate: { string_t name_string; Template* current_template = ReadTemplateDefinition( name_string, info ); if (info.templates.find(name_string) == info.templates.end()) { info.templates.insert(TemporalInfo::templates_value_t( name_string, current_template )); } else { current_template->RemRef(); } break; } case Token::TypeName: { Template* instance = ReadTemplateData(token, info); info.instances.push_back(instance); break; } } } }

Related Links