wiki:Tutorial/OpenSG1/Modelling

Previous Chapter: Clustering Tutorial Overview Next Chapter: New Action?


Modelling

One very important aspect when creating virtual environments is modelling. A powerful scenegraph system like OpenSG is not that useful at all, if there is nothing to render. So in many cases you have to feed your scenegraph with models designed with the help of a modelling package - I am sure you agree, that (hopefully) no one will create a realistic character by using standard primitive geometries...

Note: There is a useful tool with which you can examine the OpenSG graph structure of any file readable by OpenSG. Have a look here Appendix: Scene Viewer?.

Which Package to Use

If you want to create models and load them in OpenSG you have several options. You can use any application you like that can export a format OpenSG can read. So please don't be angry if your favorite application is not mentioned here.

In many cases VRML will be your format of choice, because OpenSG can read it and most applications can export VRML, too. Here are only a few great programs

  • Maxon Cinema 4D (Mac and Windows)
  • Alias Maya (Mac, Windows, Linux)
  • 3D Studio Max (Windows only)
  • Blender(Mac, Windows, Linux)

Of course these are not the only programs available, but these are really powerful.

Things Good to Know About

Exporter

Although, I personally really like Studio Max, the VRML export is quite bad. OpenSG has often problems reading those files, especially when they are big. In most cases you will get some error message, resulting in a program crash. If you have the possibility, I advise using another exporter - if you have not, it might help to weld vertices and to remove helper groups - if everything fails, try to merge the whole model into a single mesh and remove useless vertices. If that works you can split the model again in several parts either using Studio Max, or by using the osg::SplitGraphOp (see Split Grap Operator).

Another solution is to not use Studio Max at all, but another application. However, if you spent 4000 Euro for the license you might not want to do that anyway... But if you have the choice I would recommend Cinema 4D, as the files exported from Cinema were loaded correctly most times.

If you make extensive use of VRML files I also recommend using the cvs version, rather than 1.2 as of the latter the loader is a bit buggy. The cvs version does a much better job here.

Export Options

Different applications will offer you different options for export. However there are some things you have to take care of in any case. First of all, you really should export normals (if not automatically done so). If you don't OpenSG will calculate the normals when loading the file and that may take some time.

Another real life story: When developing the VR System I mentioned earlier, we had a huge VRML file containing the terrain. In our very first approch the complete terrain was stored in a single VRML file which was over 100 MB big (later we divided that in 25 pieces...). Additionally we had not stored the normals (which would make the file even bigger). Well, when we fired up our application, that was one of the moments where you think that a dual 3 GHz machine is slow...

By exporting the normals along with the other data, loading performance increased above factor 10 or so''

Furthermore you don't need to export camera position and light sources, as these are not interpreted by the loader, although that might change in the future.

Image Resource Files

If you are using textures you have to provide the image resource files, too, otherwise if OpenSG cannot find them the texture will not be loaded thus leaving your model naked! In order to find them, these files have to be placed at that location the exporter has set. If you have not had the choice to set this path, that place is where the VRML file itself lies or in a "maps" folder relative to your file. In case of Studio Max you have to specify a path.

Of course you have to make sure to use only those image types that you have compiled in support for!

Textures

Be careful with textures! Depending on the cleverness of your exporter you can run into great trouble. If you use the same material (i.e. with some texture) several times it can happen that OpenSG loads this textures as often into memory as you have assigned it. As far as I know that is the case with Studio Max, but not with Cinema 4D.

If you are working with Studio Max and have assigned a texture a hundred times, you either have to expand your memory or you have to use to use the osg::MaterialMergeGraphOp (see Material Merge). This graph operator is designed to find identical textures and reference them correctly.

Using BIN/OSB Files

VRML files are nice to transport data from your modeling package to your OpenSG application. However, it is some kind of annoying to keep track of all those image files needed and loading huge VRML files is of course not that performant, too. Here comes the BIN file format of OpenSG! If you remember the last tutorials from the basics chapter (Tutorial - loading and saving), then you know already how a BIN file can be saved from a scene currently loaded in OpenSG. But what's the big picture?

The BIN file format is a binary file format and thus is not that blithering than VRML. Furthermore all images are stored in that file, so you can not loose one of that files. And maybe most important for systems that need to load models during runtime: loading from a .bin file is much faster than from a .wrl file!

However, there is of course no application that can directly export to OpenSG BIN, so you first have to load VRML files as usual and then you can save them as BIN. A good approach could be to have a look if there is a binary version and if not the appropriate VRML is loaded and directly saved as BIN afterwards. The following example function will load a file file (with or without an extension) from disk, add it to a node node and assign it the name name.

First this function will try to load a binary version of that file (i.e file.bin), if that file is not present the appropriate VRML file will be loaded. If that also fails it will try to load the file with the given filename (maybe another file type such as .obj) and if that won't work neither it gives up.

If loading was successful and was read from a VRML file a appropriate BIN file is written, thus next time it can be loaded from that BIN file.

bool appendFileAtNode(string file, NodePtr node, string name)
{
    // at first we try to load an BIN File

    //let's assume there is a binary version
    bool binaryVersionPresent = true;

    ifstream stream((file+".bin").c_str());
    string str = file+".bin";
    if (!stream)
    {
        //There was no file "filename.bin"
        binaryVersionPresent = false;
        cerr << "> no binary version of " << file 
        << " found. Try to load VRML!" << endl;
        ifstream stream((file+".wrl").c_str());
        str = file+".wrl";
        if (!stream)
        {
            cerr << "No VRML file found for " << file 
            << ". Maybe full name given? I'll try.. " 
            << endl;

            // this is the case if the full filename was 
            // given (i.e. with extension)
            ifstream stream(file.c_str());
            str = file;
            if(!stream)
            {
                cerr << "No file found for " << file 
                     << ". Quitting! " << endl;
                return false;
            }
        }
    }

    NodePtr fileNode;
    beginEditCP(node, Node::ChildrenFieldMask);
    fileNode = SceneFileHandler::the().read(str.c_str());
    if (fileNode != NullFC)
        node->addChild(fileNode);
    else
    {
        cerr << "File " << file 
             << " could not be loaded correctly" << endl;
        return false;
    }
    node->invalidateVolume();
    endEditCP(node, Node::ChildrenFieldMask);

    // also set a resonable name
    setName(fileNode, name+" FILE");

    cout << "> " << file << " is now loaded" << endl;

    // here you could apply some graphOps if loaded from VRML

    if (!binaryVersionPresent)
    {
        // if there was no binary version write such a file now
#ifndef _WIN32
        FILE *outFile = fopen((file+".bin").c_str(), "w");
#else
        FILE *outFile = fopen((file+".bin").c_str(), "wb");
#endif

        if(outFile == NULL)
        {
            cerr << "ERROR: Cannot create file " << file+".bin" 
                 << endl;
            return false;
        }
        else
        {
            // go on : write
            BINWriter writer(outFile);

            writer.write(node);

            cout << "An binary file with the content of " << file 
                 << " has been created" << endl;
        }
    }

    return true;        
}

As described BIN files contain the whole graph and all its data, including textures. Therefore they can become quite large. But their loading time can be an order of magnitude smaller than the time for ASCII files, therefore the function above can make sense.

The BIN file use the reflective interface to be independent of additions to the system. A disadvantage of this approach is that the BIN file format is very tightly connected to the actual library. If the library is changed, by adding or removing Fields to/from an existing FieldContainer all old BIN files cannot be loaded anymore! Thus BIN should never be used as an actual storage format, it is only a cache format that can be used to reduce load times.

In versions after 1.2 there is a new binary file format called OSB which is not quite as sensitive to changes to the library as BIN. I still wouldn't use it as a storage format, but it doesn't need rewriting files every time the library changes a little bit.


Previous Chapter: Clustering Tutorial Overview Next Chapter: New Action?

Last modified 8 years ago Last modified on 01/17/10 01:11:44