Tag Archives: Back Face Culling

Geometry

This third post concerns many points of a LDraw Loader with OpenSceneGraph Library. OSG has plugins with read different format. Each plugin is related to a file format. OSG offers to create customized loader plugins. To be honest, I don't know how are constructed all formats of different 3D models. OBJ format need to read a file with the material properties and I'm not sure that it exists 3D model format which use more complex tree structure. So the LDraw format is special, made of repetitive patterns, and it needs to load many files to complete a model. A file which needs to load a file which needs to load a file ...

Application which uses Qt and OpenSceneGraph. It displays LDraw format. At the right of the window, the tree corresponds to the graph of OSG. At the left, there are many data about the selected item (here transformmatrix)
Application which uses Qt and OpenSceneGraph. It displays LDraw format. At the right of the window, the tree corresponds to the graph of OSG. At the left, there are many data about the selected item (here transformmatrix)

For the LDraw loader, I don't want use recursive algorithms because bugs may easily appear. The second point, I need to keep all of the loaded file in memory and avoid to load many times the same pattern. I think it exists in OSG a mechanism to avoid this but I'm not sure of its use. So I have chosen to have a list of models and I have split the loading process into 2 parts: the loading of the data from a file and a mechanism which links models. So when the program load data, it creates a geometry model and stores the name of the model. Next, the model is put in the models list. During the second step, for each loaded model, the program reads the name of children. If the file is already loaded, it creates a link to the corresponding model, else it loads the file and store it in the queue of the list of models. This system is easy to implement but I don't know if it is the best method. Nevertheless, it appears that LDraw models are a support to avoid to recreate model and I will use an another format in my future applications.

A second difficulty concerns a strange choice about the Back Face Culling. The BFC avoids to display faces which aren't visible by the camera. In fact, it is interesting for speed gain during rendering. There are two modes: Clockwise and Counter-Clockwise. LDraw use CCW by default but can use CW and many time a subpart of a model need to invert the BFC mode. For example, to create a hollow cylinder, the author need use twice a cylindrical surface: an external surface and an internal surface. The two surfaces correspond to the same model with a different scale. If the BFC mode is the same for all surfaces, a camera in the center of the hollow cylinder will display no one of the surfaces. So the author of the part needs to invert the BFC of the internal surface. In the LDraw format, the Meta-Command 'INVERTNEXT' allows to change the BFC of the next submodel. I have chose to duplicate the model and flip all geometries and submodels. The new model is registered to the models list with the suffix '_INVERT'. My main use of the BFC concerns the direction of the normal vectors (for light reflexion). There is an another problem with BFC: if there are a negative scale for a submodel (the determinant of the transformation matrix is negative), BFC need to be inverted. So there are two types of inversion: an inversion of a model and a inversion due to transformations (translate, rotate, scale). An inverted model has inverted normal but transformation may change BFC but not normals. For display a brick as an group of submodel, I prefer deactivate the BFC. When I will merge all geometries of a brick in a unique object, it will be possible to reactivate BFC.

In the next post, I will talk about the colors and the Level Of Detail. Currently, only a basic LOD is implemented. This corresponds to a Ldraw specifications for the resolution mesh of a curved surface (as cylinders).