<< Previous Chapter: Using the fcd2code generator Tutorial Overview Next Chapter: Debugging Tips >>

Creating a new container type

We will create a new type of NodeCore that can render cubes. The example demonstrates tow ways of doing this:

  • placing the new container in a separate shared library (CubesLib) and a short GLUT-based program linked against that library that uses the new type (CubesApp)
  • making the new container part of the application, i.e. just link all the sources together in the executable without building a new shared library.

The following is a step by step description of the process, written while the example was ported from OpenSG 1.x to 2.0. It is written in a manner that describes the process as if the new container was created from scratch, it is not meant as a porting guide.

CubesLib and CubesApp

Write OSGCubes.fcd

Open the link in a new tab/window to see the contents of OSGCubes.fcd. We name our new container type simply "Cubes" and derive it from "MaterialDrawable". Since the type itself is not part of OpenSG (it will live in a separate shared library) we set systemcomponent to "false", but parentsystemcomponent to "true" (MaterialDrawable belongs to OpenSG).

Since we know that the container will render cubes, we only specify a position and size (length, i.e. the length of an edge of the cube) as well as a colour. All three fields are "multi" fields, because we want our type to render many cubes not just one.

The .fcd file format is described in more detail in Using the fcd2code generator.

Generate the source files

Run fcd2code and generate the Base and User files (options -b and -f). You will get the following files:

Base files
User files

See Using the fcd2code generator for detailed information on the tool and the .fcd file format

Edit User files

Add drawPrimitives() member function. All (non-abstract) types derived from MaterialDrawable must define this function. This is the function that gets called to render the drawable. Here we just use immediate mode to draw some cubes, a better implementation would use display lists or VBOs to speed things up.

Add fill() member function. It is used to gather some statistics about the Drawable, so we fill in the number of vertices and triangles that are rendered for our cubes.

Add adjustVolume() member function. This is used to make sure the frustum culling works correctly. The implementation is rather simple, it simply extends the volume to contain each corner of every cube. More efficient implementations could cache that information an only update it if the member fields are modified.

Write a library import/export header (OSGCubesLibDef.h). In theory this would only be needed on windows (it contains the macros for dllimport/dllexport annotations), but since the macros have to be present in the generated code as well, the macros need to be defined on all platforms. For a new library just copy the contents of an existing OSG<name>Def.h header and replace all occurrences of <name> in it with the name of your library - don't forget the include guards right below the copyright notice!

Write a CMakeLists.txt file to compile the CubesLib library

This step is somewhat optional, of course you don't have to use cmake to compile the library, but can use your preferred build system to get the job done. The CMakeLists.txt is pretty straightforward:

  • set the minimal cmake version and project name
  • make sure the FindOpenSG.cmake module is found (by adding to CMAKE_MODULE_PATH)
  • gather all the source files
  • collect all dependencies (only boost and !OpenSG) and store them in variables
  • pass the information to cmake and instruct it to build a library from the sources

Compile CubesLib

create a build directory (we refer to it as <build> in the following) and run cmake with the following arguments (optional if both boost and !OpenSG are installed in a standard location for your system, e.g. /usr):

cmake -DBOOST_ROOT=<path_to_boost> -DOPENSG_ROOT=<path_to_opensg> <source>

Where <source> is the path to the Examples/CustomIntegration/NewContainerType/CubesLib directory. This will generate a build system (e.g. Makefile or VS project) which then is used to compile CubesLib.

Write CubesApp

CubesApp is a very simple test program based on glut that demos the new Cubes drawable. The init() function creates the !GLUTWindow and a single cubes core as well as the SimpleSceneManager to hold everything together. The main() function only calls init() and then goes into glutMainLoop() and in case that returns in your GLUT implementation calls fini() to clean everything up.

Write a CMakeLists.txt file to compile the CubesApp application

This one looks very similar to the one use to build CubesLib, the main difference is that this time we need a few more OpenSG libraries (namely !OSGWindow, !OSGWindowGLUT and a platform specific window implementation). Of course, we also need to link against the CubesLib, so there is a new section for this dependency. It has some code that reminds you how to tell cmake where to find CubesLib, but the main element is the call to FIND_LIBRARY().

Compile CubesApp

The final step is to compile the application. As with the lib we start by creating a build directory (don't reuse the one for the lib, create a new one) and run cmake in it:

cmake -DBOSOT_ROOT=<path_to_boost> -DOPENSG_ROOT=<path_to_opensg>
-DCUBESLIB_ROOT=<build> <source>

Here <build> is the directory where you built the CubesLib library and <source> is the path to Examples/CustomIntegration/NewContainerType/CubesApp.

Run CubesApp

After building CubesApp you need to make sure it can find all the necessary libraries at runtime (on linux this is not a problem, the paths are compiled into the executable, i.e. the --rpath argument to the linker is used). On Windows this means the PATH environment variable has to contain all directories where the various needed DLLs are (i.e. !OpenSG, CubesLib, GLUT). When everything worked you should see a window with a bunch of colourful cubes in it. You can control your view with the mouse (hold button 1)

Unified CubesApp

Write OSGCubes.fcd

Identical to the case for CubesLib, see above.

Generate the source files

Identical to the case for CubesLib, see above.

Write CubesApp

Identical to the case for CubesLib, see above.

Edit User files

Here a small modification is necessary: the OSGCubesLibDef.h header needs to have a slightly different content. Instead of defining OSG_CUBESLIB_DLLMAPPING to either dllimport or dllexport, we just unconditionally define it to nothing. After all this example does not put the code into a shared library/DLL so we don't need any of the annotations. Do NOT use that file as a copy&paste source if you want to put containers in a shared library/DLL!

Write CMakeLists.txt file to compile CubesAppUnified application including the sources for the new container

This file is very similar to the one used for CubesApp, except that it does not need to locate CubesLib as a dependency, but instead we make sure the source directory is searched for headers.

Compile CubesApp

Create a new build directory and call run cmake in it:

cmake -DBOOST_ROOT=<path_to_boost> -DOPENSG_ROOT=<path_to_opensg> <source>

Here source is the path to Examples/CustomIntegration/NewContainerType/CubesAppUnified.

Run CubesAppUnified

The same remarks as for CubesApp apply, see above.

<< Previous Chapter: Using the fcd2code generator Tutorial Overview Next Chapter: Debugging Tips >>
Last modified 6 years ago Last modified on 10/05/11 00:22:07