In This Article:

UNIGINE's Import System allows you to import models and scenes in various external formats (FBX, DAE, OBJ, etc.). Although the basic set of file formats supported by UNIGINE out-of-the-box includes the most commonly used ones, in some cases you may need to import models or scenes in some specific file format. Fortunately the Import System can be extended to support any custom file format.

This example demonstrates how to:

Implement your own custom importer as a plugin.

Create your own import pre-processor.

Use your custom importer to bring a scene stored in a custom file format to UNIGINE.

So, in this example we are going create a custom importer for a custom file format. Let it be an xml-based format in which we declare our scene as a hierarchy of nodes that have a transformation and can have a mesh, light or camera attribute. Let our file format have a .myext exstension. An example of a scene in our custom format containing all available elements is given below.

For our importer we're going to create and use a custom pre-processor to reset light colors to white when the corresponding flag is set. Thus, we're going to have the following import options and parameters:

scale - scale factor to be used for imported scene

vertex_cache - vertex cache optimization for meshes

make_lights_white - reset light colors flag for our pre-processor

At the end of this example we're going to have this model imported to UNIGINE's world and saved in UNIGINE's native file formats in the specified folder. But before we get started, a little bit of theory (as key points).

UNIGINE's API offers us a set of classes for implementing customized model import.

All meta information about your imported scene should be stored in an instance of the ImportScene class. Basically a scene may contain meshes (ImportMesh), lights (ImportLight), cameras (ImportCamera), and other elements (see the complete list here). You can specify which of these scene components are to be imported using the corresponding import flags (IMPORT_MESHES, IMPORT_LIGHTS, etc.)

As you know each importer should be implemented as a plugin. So we're going to create a C++ plugin.

So, we inherit our import plugin from the Plugin class. We specify plugin name by overriding the get_name() method and also override init() and shutdown() methods to perform initialization and cleanup.
We will have the following header file:

First we should define some intermediate data structures to which all parameters of imported scene elements are to be extracted. And we should declare a common template for UserData to be able to assign data to the import structures.

Use pre-processor(s) to prepare scene metadata when necessary (e.g. merge all static meshes into a single one, optimize vertex cache, etc.). In our example we're going to strip off light color information if the corresponding option (make_lights_white) is set.

Process scene metadata corresponding to the type of imported scene element and create UNIGINE objects (nodes, meshes, lights, cameras, etc.). This is performed in overrides of Importer::onImport*() methods, i.e. for lights we'll have MyImporter::onImportlight() looking as follows:

Save generated UNIGINE objects to *.node and *.mesh files. This part is performad by the DefaultProcessor, so we do nothing here.

And there are a couple more things we should think of for our importer: initialization and cleanup operations, which are implemented in the constructor and destructor respectively. So, upon construction we should set default import parameters and add necessary processors. While in the cleanup section we should remove all added processors. In our case we have:

Add and use the plugin in the world script via engine.addPlugin(). The same can be done in the project's world logic via Engine::addPlugin() on the C++ side or viaEngine.addPlugin() on the C# side of the project.

Add and use the plugin in the system script (unigine.cpp):

Add the plugin via engine.addPlugin() and use it in the world script. You cannot initialize the plugin in the system script and call plugin functions from it at the same time.

Use the plugin in the system script after initializing it via the command-line argument
extern_plugin.

The same can be done in the project's system logic via
Engine::addPlugin() on the C++ side or via Engine.addPlugin() on the C# side of the project.

Use the plugin in our project. Let's add some lines of code to the init() method of the world script (MyProject.cpp file) to demonstrate the idea.