5. gpExport - a Maya Exporter -- gpExport

During this project an exporter-framework emerged: gpExport. It extracts typical model-information game-exporters need. The developer just needs to implement the writing-part of the plug-in.

5.1 Architecture

Although the UML-diagram doesn't show it, all classes inherit virtually from gpBase, which is just a helper-class providing a status-variable (needed for almost all Maya-calls), and ways to check it.

The doXXX- and shouldXXX-functions are template-methods, to configure the exporter. They are all taken care of by GPExporter, which takes the configuration from the exporterConfig, that has been passed to it (IExporterConfig is basically just an interface for all these parameters).

In addition to the shown classes, gpExport provides two additional classes:

  • a converter-class
  • and a fileWriter-class
Both of them are utility-classes for implementing the abstract WriteScene-method.


5.2 Extending gpExport

This section essentially describes, how to use gpExport to easily implement a standard exporter. I'll take MS3D (MilkShake3D) as example. As this is really not a MS3D-tutorial, I won't go into details for the writing-part though.

5.2.1 Exporter

Let's start by completing the GPExporter-class ms3dExporter.hpp:

19:     class MS3DExporter
20:         : virtual protected GPBase,
21:           public GPExporter,
22:           protected MS3DWriter
23:     {
24:     public:
25:         void Export(const IExporterConfig& config)
26:             { GPExporter::Export(config); }
27: 
28:     protected:
29:         void WriteScene(const Scene& extractedScene,
30:                         const std::string& outFile)
31:             { MS3DWriter::WriteScene(extractedScene, outFile); }
32:     };

MS3DExporter redirects its Export-method to the GPExporter-part, which will call WriteScene after having extracted the necessary information. WriteScene itself is forwarded to the MS3DWriter-part.

MS3DWriter on the other hand uses Converter and FileWriter to do its task. In particulary it doesn't implement the WriteScene itself, but provides the doWriteScene-method, which is called by the FileWriter-class.

Completing the GPExporter-class is not sufficient. One still needs to create a plugin or executable.

5.2.2 Plugin

gpExport already provides a basic plugin-class, that should be sufficient for most uses. Obviously it isn't complete, as the plugin-class contains exporter-specific information (the name, extension, etc.). Information, that can be demanded at runtime over virtual methods are pure virtual in the gpExport-plugin class. These are the getExtension- and Export-method. A custom exporter therefore needs to implement these methods (ms3dPlugin.cpp):

16:     class MS3DPlugin
17:         : public GPTranslation::Plugin

21:         // template-method (of GPTranslation::Plugin)
22:         std::string
23:         getExtension() const
24:             {
25:                 return extension;
26:             }

47:         void
48:         Export(const IExporterConfig& config)
49:             {
50:                 // MS3DExporter::Export(config); // can't do :(
51:                 MS3DExporter exporter;
52:                 exporter.Export(config);
53:             }

In addition Maya needs two static methods: initializePlugin and uninitializePlugin. initializePlugin provides a plugin-description (MPnPlugin) to Maya, and registers the exporter (translator). One parameter is a static function, that allows to create our translator:

31:         static
32:         void*
33:         creator()
34:             {
35:                 return new MS3DPlugin();
36:             }

57: MStatus initializePlugin(MObject obj)
58: {
59:     using namespace MS3DTranslation;
60: 
61:     MFnPlugin plugin(obj,
62:                      vendor,
63:                      version,
64:                      requiredApiVersion);
65: 
66:     // Register the translator:
67:     return plugin.registerFileTranslator(translatorName,
68:                                          (char*)pixmapName,
69:                                          MS3DPlugin::creator,
70:                                          (char*)optionsScript,
71:                                          (char*)defaultOptions);
72: }

All those variables (vendor, ...) have been defined earlier:

 7:     const char* const translatorName = "MS3D_Export";
 8:     const char* const pixmapName = "none";
 9:     const char* const optionsScript = "MS3D_opts";
10:     const char* const defaultOptions = "";
11:     const char* const extension = "ms3d";
12:     const char* const vendor = "OpenSource";
13:     const char* const version = "0.1";
14:     const char* const requiredApiVersion = "Any";

And now finally the uninitializePlugin-function:

74: MStatus uninitializePlugin(MObject obj)
75: {
76:     MFnPlugin plugin(obj);
77:     return plugin.deregisterFileTranslator(MS3DTranslation::translatorName);
78: }

5.2.3 Executable

The code for executables is even simpler: One just needs to provide the classical main-function, and call exportScene of the executable.hpp-header (ms3dExecutable):

10: int
11: main(int argc, char** argv)
12: {
13:     try
14:     {
15:         if (argc != 3)
16:         {
17:             printUsage(argv[0]);
18:             return -1;
19:         }
20: 
21:         MS3DTranslation::MS3DExporter exporter;
22:         
23:         GPTranslation::exportScene(argv[0],
24:                                    exporter,
25:                                    argv[1],
26:                                    argv[2]);
27:         return 0;
28:     }
29:     catch (...)
30:     {
31:         return -1;
32:     }
33: }

And here's the signature of the exportScene-function:

13:     void exportScene(const std::string& exporterName,
14:                      GPExporter& exporter,
15:                      const std::string& inFile,
16:                      const std::string& outFile);

This simplicity induces some restrictions: there's no way of paramizing the exporter. If this is needed (which is usually the case), one needs to copy some lines out of the executable.cpp-file, and implement the exportScene-method on his own. Fortunately the code is short (6 code-lines) and not difficult.

The only difficulty in creating executables lies in the linking. A Maya-executable needs a bunch of libraries (in the correct order). If you want to win some time, use gpExport's Makefile.



This Html page has been produced by Skribe.
Last update Sun Sep 5 10:51:24 2004.