DOM guide: Integration templates: Difference between revisions

From COLLADA Public Wiki
Jump to navigation Jump to search
Elf (talk | contribs)
m catg sort
Elf (talk | contribs)
DAE object->DOM object
Line 1: Line 1:
When you [[DOM guide: Loading and saving documents|load]] a [[COLLADA XML instance document]] into the [[COLLADA DOM]], it creates a DAE object for each XML element in the COLLADA document. An application can then use DOM methods to read and manipulate the DAE objects. However, your application might already have its own data structures designed to represent the data coming from COLLADA XML elements and its own tools for manipulating those data structures. In that case, you can implement the COLLADA DOM's '''integration templates''', which, when loading a COLLADA document, convert DAE objects into your application's data structures, and back again when saving.  
When you [[DOM guide: Loading and saving documents|load]] a [[COLLADA XML instance document]] into the [[COLLADA DOM]], it creates a DOM object for each XML element in the COLLADA document. An application can then use DOM methods to read and manipulate the DOM objects. However, your application might already have its own data structures designed to represent the data coming from COLLADA XML elements and its own tools for manipulating those data structures. In that case, you can implement the COLLADA DOM's '''integration templates''', which, when loading a COLLADA document, convert DOM objects into your application's data structures, and back again when saving.  


This article provides a step-by-step example of how to integrate application data structures with the COLLADA runtime infrastructure ([[COLLADA DOM]]). Detailed knowledge of the COLLADA DOM architecture is not necessary to understand this example or to successfully integrate your own application-specific data structures.
This article provides a step-by-step example of how to integrate application data structures with the COLLADA runtime infrastructure ([[COLLADA DOM]]). Detailed knowledge of the COLLADA DOM architecture is not necessary to understand this example or to successfully integrate your own application-specific data structures.


==Overview==
==Overview==
The [[COLLADA Object Model]] is a set of runtime [[COLLADA DAE object]]s that correspond to elements in a [[COLLADA XML instance document]] (a ''COLLADA document'''). For importing, the COLLADA DOM builds these objects when it parses a COLLADA document. For exporting into a COLLADA  document, you might need to provide code to build the appropriate DAE objects.  
The [[COLLADA Object Model]] is a set of runtime [[COLLADA DOM object]]s that correspond to elements in a [[COLLADA XML instance document]] (a ''COLLADA document'''). For importing, the COLLADA DOM builds these objects when it parses a COLLADA document. For exporting into a COLLADA  document, you might need to provide code to build the appropriate DOM objects.  


To convert data contained in COLLADA DAE objects into your own application's data structures, and the reverse, the DOM provides integration templates for every object. The integration templates include plug-in points where you can insert conversion code (otherwise, the templates do nothing). After a COLLADA document has been imported by the DOM into COLLADA DAE objects, or when you request an export, the DOM calls your conversion code to perform the convert between the DAE objects and the application's data structures.  
To convert data contained in COLLADA DOM objects into your own application's data structures, and the reverse, the DOM provides integration templates for every object. The integration templates include plug-in points where you can insert conversion code (otherwise, the templates do nothing). After a COLLADA document has been imported by the DOM into COLLADA DOM objects, or when you request an export, the DOM calls your conversion code to perform the convert between the DOM objects and the application's data structures.  


:'''The following figure shows what happens during a ''load'' when integration templates are used.'''
:'''The following figure shows what happens during a ''load'' when integration templates are used.'''
Line 12: Line 12:


The basic steps during integration are the following:
The basic steps during integration are the following:
#Application initializes the COLLADA DOM by creating a new DAE object.
#Application initializes the COLLADA DOM by instantiating one object of the '''DAE''' class.
#Application registers its application-specific integration libraries.
#Application registers its application-specific integration libraries.
#When importing a COLLADA document:
#When importing a COLLADA document:
##Application begins the import by calling '''load'''; the DOM reads the COLLADA document and places its elements into runtime COLLADA DAE objects. COLLADA DAE objects with registered integration libraries automatically create their associated application data structures.
##Application begins the import by calling '''load'''; the DOM reads the COLLADA document and places its elements into runtime COLLADA DOM objects. COLLADA DOM objects with registered integration libraries automatically create their associated application data structures.
##The COLLADA runtime calls the conversion methods in the integration libraries to convert the content of COLLADA DAE objects into their associated data structures.
##The COLLADA runtime calls the conversion methods in the integration libraries to convert the content of COLLADA DOM objects into their associated data structures.
#When exporting to a COLLADA document:
#When exporting to a COLLADA document:
##If COLLADA DAE objects don’t already exist for the COLLADA elements that you want to export, application calls '''createTo''' to create them.
##If COLLADA DOM objects don’t already exist for the COLLADA elements that you want to export, application calls '''createTo''' to create them.
##Application begins the export of a COLLADA DAE structure by calling '''save'''; the COLLADA runtime calls registered conversion methods in the integration libraries to convert the content of the application's data structures into COLLADA DAE objects and then exports the DAE objects to elements in a COLLADA document.
##Application begins the export of a COLLADA DAE structure by calling '''save'''; the COLLADA runtime calls registered conversion methods in the integration libraries to convert the content of the application's data structures into COLLADA DOM objects and then exports the DOM objects to elements in a COLLADA document.


==COLLADA DOM Integration Templates==
==COLLADA DOM Integration Templates==
At import time, the DOM loads elements from COLLADA documents into DAE objects in a run-time COLLADA Object Model. The COLLADA DOM provides integration templates to enable you to convert COLLADA data between the DAE objects and your own run-time data structures. ''((ELLEN: Note to self: This is redundant from above; consider removing...))''
At import time, the DOM loads elements from COLLADA documents into DOM objects in a run-time COLLADA Object Model. The COLLADA DOM provides integration templates to enable you to convert COLLADA data between the DOM objects and your own run-time data structures. ''((ELLEN: Note to self: This is redundant from above; consider removing...))''


Each DAE object has its own integration template consisting of a header (.h) file and a code (.cpp) file.  For example, the DAE object for the COLLADA <node> element is  '''domNode''', and the template files to convert '''domNode''' objects to or from application data structures are '''intNode.cpp''' and '''intNode.h'''. ''((ANDY: If I got this paragraph right, then I think  I need to change the diagram to use domElement1 object and domElementA object (instead of element1 obj and elementA obj)? ))''
Each DOM object has its own integration template consisting of a header (.h) file and a code (.cpp) file.  For example, the DOM object for the COLLADA <node> element is  '''domNode''', and the template files to convert '''domNode''' objects to or from application data structures are '''intNode.cpp''' and '''intNode.h'''. ''((ANDY: If I got this paragraph right, then I think  I need to change the diagram to use domElement1 object and domElementA object (instead of element1 obj and elementA obj)? ))''


Copy into your application directory the template files for the elements that you want to convert from DAE objects into application-specific data structures or vice versa. These copies are the starting points for your customized integration libraries. You can then add code to these integration libraries to convert data between DAE objects and their associated application data structures.
Copy into your application directory the template files for the elements that you want to convert from DOM objects into application-specific data structures or vice versa. These copies are the starting points for your customized integration libraries. You can then add code to these integration libraries to convert data between DOM objects and their associated application data structures.


The plug-in points for your code are identified in comments in the template source.
The plug-in points for your code are identified in comments in the template source.


The COLLADA DOM provides two sets of integration templates:
The COLLADA DOM provides two sets of integration templates:
*Simple integration templates: These templates are in the templates/integrationSimple directory, and provide plug-in points for a basic set of COLLADA elements. These templates do not provide plug-in points for nested COLLADA elements, such as the '''<author>''' element found in '''<asset>''' that is defined by the '''domAuthor''' DAE object class.
*Simple integration templates: These templates are in the templates/integrationSimple directory, and provide plug-in points for a basic set of COLLADA elements. These templates do not provide plug-in points for nested COLLADA elements, such as the '''<author>''' element found in '''<asset>''' that is defined by the '''domAuthor''' DOM object class.
*Full integration templates: These templates are in the templates/integrationFull directory, and provide plug-in points for all COLLADA elements.
*Full integration templates: These templates are in the templates/integrationFull directory, and provide plug-in points for all COLLADA elements.


==Integration Objects==
==Integration Objects==
Your integration library for each DAE object provides the code that defines an integration object for that object. The integration object serves as the focal point for all information about the conversion. It defines methods that perform the conversion, and it provides data members that bind the DAE object with the application-specific data structure being converted to.
Your integration library for each DOM object provides the code that defines an integration object for that object. The integration object serves as the focal point for all information about the conversion. It defines methods that perform the conversion, and it provides data members that bind the DOM object with the application-specific data structure being converted to.


Integration objects are represented with the '''daeIntegrationObject''' class. Every class derived from '''daeElement''' provides for an integration object through the data member '''daeElement::_intObject'''.
Integration objects are represented with the '''daeIntegrationObject''' class. Every class derived from '''daeElement''' provides for an integration object through the data member '''daeElement::_intObject'''.
Line 41: Line 41:
The integration object class for each element is defined with the prefix “int”. For example, the '''domGeometry''' DAE class provides an '''intGeometry''' integration object.
The integration object class for each element is defined with the prefix “int”. For example, the '''domGeometry''' DAE class provides an '''intGeometry''' integration object.


When you define integration code for a DAE object, your code binds the DAE object with your application-specific object, via the '''_element''' and '''_object''' data members of the integration object. You can use methods '''daeIntegrationObject::getElement()''' and '''getObject()''' to access these data members.
When you define integration code for a DOM object, your code binds the DOM object with your application-specific object, via the '''_element''' and '''_object''' data members of the integration object. You can use methods '''daeIntegrationObject::getElement()''' and '''getObject()''' to access these data members.


When you load a COLLADA instance document, the DOM automatically creates the appropriate integration objects.  
When you load a COLLADA instance document, the DOM automatically creates the appropriate integration objects.  
Line 48: Line 48:


==Integration Template Plugin Points==
==Integration Template Plugin Points==
The integration class for each DAE object provides six plug-in points into which you can add conversion code. The plug-in points are implemented as methods; you provide the code for the method bodies. You need to implement the body of the methods only for those plug-in points that are relevant to your application.
The integration class for each DOM object provides six plug-in points into which you can add conversion code. The plug-in points are implemented as methods; you provide the code for the method bodies. You need to implement the body of the methods only for those plug-in points that are relevant to your application.


The methods are:
The methods are:
*'''createFrom()''': Defines the code to create the application-specific data structure associated with the DAE class for this template. This method sets up the integration object for the DAE class.
*'''createFrom()''': Defines the code to create the application-specific data structure associated with the DAE class for this template. This method sets up the integration object for the DAE class.
*'''fromCOLLADA()''': Defines the code to covert a DAE object into your application-specific data structure.
*'''fromCOLLADA()''': Defines the code to covert a DOM object into your application-specific data structure.
*'''fromCOLLADAPostProcess()''': Defines any postprocessing code that must execute after the basic conversion to your data structure.
*'''fromCOLLADAPostProcess()''': Defines any postprocessing code that must execute after the basic conversion to your data structure.
*'''createTo()''': Defines code to create the DAE object associated with the DAE class for this template if such a structure does not already exist (for example, if it was not created while importing).
*'''createTo()''': Defines code to create the DOM object associated with the DAE class for this template if such a structure does not already exist (for example, if it was not created while importing).
*'''toCOLLADA()''': Defines the code to covert the content of your application’s data structures into DAE objects.
*'''toCOLLADA()''': Defines the code to covert the content of your application’s data structures into DOM objects.
*'''toCOLLADAPostProcess()''': Defines any postprocessing code that must execute after the basic conversion from your application’s data structure.
*'''toCOLLADAPostProcess()''': Defines any postprocessing code that must execute after the basic conversion from your application’s data structure.


Line 80: Line 80:


===Setting up the Integration Library Header File===
===Setting up the Integration Library Header File===
Now edit the new integration library for the objects to be converted. Start with the '''intGeometry.h''' integration library copied from the '''intGeometry.h''' template. The template must be modified to add information about the application data structures to or from which the DAE object will be converted. For the header, declare the class to be converted into or from:
Now edit the new integration library for the objects to be converted. Start with the '''intGeometry.h''' integration library copied from the '''intGeometry.h''' template. The template must be modified to add information about the application data structures to or from which the DOM object will be converted. For the header, declare the class to be converted into or from:
  // class myGeometry is fully defined in an application header file.
  // class myGeometry is fully defined in an application header file.
  class myGeometry;
  class myGeometry;
Line 99: Line 99:


===Defining Your Application Data Structure===
===Defining Your Application Data Structure===
Within the integration library files, provide the code to create your application-specific data structure for the COLLADA DAE objects that you want to convert.
Within the integration library files, provide the code to create your application-specific data structure for the COLLADA DOM objects that you want to convert.


For this example, the application's  data structure used to represent geometry is defined in an application header file, in this case, '''myGeometry.h''':
For this example, the application's  data structure used to represent geometry is defined in an application header file, in this case, '''myGeometry.h''':
Line 125: Line 125:


===Build Conversion Code for Importing===
===Build Conversion Code for Importing===
Now add code to the integration library to translate the data stored in a DAE object to its associated application data structure. The '''fromCOLLADA()''' method is the plug-in point for the basic application-specific conversion code. The '''fromCOLLADAPostProcess()''' method provides additional flexibility for the conversion process.
Now add code to the integration library to translate the data stored in a DOM object to its associated application data structure. The '''fromCOLLADA()''' method is the plug-in point for the basic application-specific conversion code. The '''fromCOLLADAPostProcess()''' method provides additional flexibility for the conversion process.


Depending on the COLLADA DAE object and the application data structure, the code may vary significantly. For this example, we use the '''intGeometry::fromCOLLADA()''' method to create new vertex buffers from the COLLADA DAE geometry object.
Depending on the COLLADA DOM object and the application data structure, the code may vary significantly. For this example, we use the '''intGeometry::fromCOLLADA()''' method to create new vertex buffers from the COLLADA DAE geometry object.


The following code retrieves the mesh object from the COLLADA '''domGeometry''' object:
The following code retrieves the mesh object from the COLLADA '''domGeometry''' object:
Line 202: Line 202:


===Access COLLADA Objects from the Application===
===Access COLLADA Objects from the Application===
Now put together the application code that registers the integration libraries, loads the COLLADA elements into the in-memory DAE objects, and accesses the converted data.  
Now put together the application code that registers the integration libraries, loads the COLLADA elements into the in-memory DOM objects, and accesses the converted data.  


====Invoke Integration Libraries Registration====
====Invoke Integration Libraries Registration====
You defined the '''intRegisterElements()''' function as described in “Register Integration Libraries with the DOM.” Now you must pass a handle to this function into the '''DAE::setIntegrationLibrary()''' method.
You defined the '''intRegisterElements()''' function as described in “Register Integration Libraries with the DOM.” Now you must pass a handle to this function into the '''DAE::setIntegrationLibrary()''' method.


With this step, the elements that you want to convert are registered with the DOM, and are converted from COLLADA DAE objects to application-specific structures when a COLLADA document is loaded, or the reverse when an object is saved.
With this step, the elements that you want to convert are registered with the DOM, and are converted from COLLADA DOM objects to application-specific structures when a COLLADA document is loaded, or the reverse when an object is saved.


For example, your main application code could pass a handle to the integration library registration function as follows:
For example, your main application code could pass a handle to the integration library registration function as follows:
Line 216: Line 216:


====Parse a COLLADA File====
====Parse a COLLADA File====
Now parse a COLLADA document into the run-time COLLADA Object Model. The load step creates the integration objects and invokes the '''createFrom()''' and '''romCOLLADA()''' methods to convert the data from the COLLADA DAE objects into the application-defined data structures.
Now parse a COLLADA document into the run-time COLLADA Object Model. The load step creates the integration objects and invokes the '''createFrom()''' and '''romCOLLADA()''' methods to convert the data from the COLLADA DOM objects into the application-defined data structures.
  //load the COLLADA file
  //load the COLLADA file
  int res = daeObject->load(filename);
  int res = daeObject->load(filename);
Line 227: Line 227:


====Acquire the Converted Application Object====
====Acquire the Converted Application Object====
In the following code, the '''myGeometry''' class represents the application data structure containing geometry data. The COLLADA DAE object retrieved above into '''pElem''' contains a reference to its associated integration object (thanks to its earlier registration). The '''intGeometry''' class converts the COLLADA data ''((ELLEN: which collada data are we talking about here?))'' and returns the converted data as a '''myGeometry''' instance via the '''getGeometry()method''', which was defined in '''importGeometry.h'''.
In the following code, the '''myGeometry''' class represents the application data structure containing geometry data. The COLLADA DOM object retrieved above into '''pElem''' contains a reference to its associated integration object (thanks to its earlier registration). The '''intGeometry''' class converts the COLLADA data ''((ELLEN: which collada data are we talking about here?))'' and returns the converted data as a '''myGeometry''' instance via the '''getGeometry()method''', which was defined in '''importGeometry.h'''.
  // Get the integration object from the element
  // Get the integration object from the element
  daeIntegrationObject *pIntegrationObj = pElem->getIntObject();
  daeIntegrationObject *pIntegrationObj = pElem->getIntObject();
Line 245: Line 245:
In some cases, you might need to export your data to an entirely new COLLADA document, such as when the data originated in your application rather than by being imported from an existing COLLADA instance document. In this cases, to use the integration methods to convert from your application structure to a DOM object and then export to a new COLLADA instance document, you must create the matching COLLADA DOM structure before you can convert from your application’s structure.
In some cases, you might need to export your data to an entirely new COLLADA document, such as when the data originated in your application rather than by being imported from an existing COLLADA instance document. In this cases, to use the integration methods to convert from your application structure to a DOM object and then export to a new COLLADA instance document, you must create the matching COLLADA DOM structure before you can convert from your application’s structure.


Compare with the import process: When your application loads a COLLADA instance document, the COLLADA DOM automatically creates DAE objects in which to load the COLLADA data, then calls your customized createFrom for each element that has an integration class, which creates your application-specific objects. Then it calls fromCOLLADA, which copies the data from the DAE objects to your application objects.
Compare with the import process: When your application loads a COLLADA instance document, the COLLADA DOM automatically creates DOM objects in which to load the COLLADA data, then calls your customized createFrom for each element that has an integration class, which creates your application-specific objects. Then it calls fromCOLLADA, which copies the data from the DOM objects to your application objects.


If you create a new application object, there are no COLLADA elements (no DAE objects) associated with it. If you simply save the file, this new data is not written. The purpose of createTo is to create these COLLADA elements and associate them with the application object. createTo is not called automatically when a new application object is created; you must call it explicitly. After createTo has been called, the rest of the saving process is automatic, that is, if you have registered your integration library, when you call save, toCOLLADA is called for every COLLADA element with an integration class to copy the data from the application objects into the COLLADA objects.
If you create a new application object, there are no COLLADA elements (no DOM objects) associated with it. If you simply save the file, this new data is not written. The purpose of createTo is to create these COLLADA elements and associate them with the application object. createTo is not called automatically when a new application object is created; you must call it explicitly. After createTo has been called, the rest of the saving process is automatic, that is, if you have registered your integration library, when you call save, toCOLLADA is called for every COLLADA element with an integration class to copy the data from the application objects into the COLLADA objects.


This example code does not show how to do this. The createTo method looks like this:
This example code does not show how to do this. The createTo method looks like this:

Revision as of 20:57, 30 March 2007

When you load a COLLADA XML instance document into the COLLADA DOM, it creates a DOM object for each XML element in the COLLADA document. An application can then use DOM methods to read and manipulate the DOM objects. However, your application might already have its own data structures designed to represent the data coming from COLLADA XML elements and its own tools for manipulating those data structures. In that case, you can implement the COLLADA DOM's integration templates, which, when loading a COLLADA document, convert DOM objects into your application's data structures, and back again when saving.

This article provides a step-by-step example of how to integrate application data structures with the COLLADA runtime infrastructure (COLLADA DOM). Detailed knowledge of the COLLADA DOM architecture is not necessary to understand this example or to successfully integrate your own application-specific data structures.

Overview

The COLLADA Object Model is a set of runtime COLLADA DOM objects that correspond to elements in a COLLADA XML instance document (a COLLADA document'). For importing, the COLLADA DOM builds these objects when it parses a COLLADA document. For exporting into a COLLADA document, you might need to provide code to build the appropriate DOM objects.

To convert data contained in COLLADA DOM objects into your own application's data structures, and the reverse, the DOM provides integration templates for every object. The integration templates include plug-in points where you can insert conversion code (otherwise, the templates do nothing). After a COLLADA document has been imported by the DOM into COLLADA DOM objects, or when you request an export, the DOM calls your conversion code to perform the convert between the DOM objects and the application's data structures.

The following figure shows what happens during a load when integration templates are used.

The basic steps during integration are the following:

  1. Application initializes the COLLADA DOM by instantiating one object of the DAE class.
  2. Application registers its application-specific integration libraries.
  3. When importing a COLLADA document:
    1. Application begins the import by calling load; the DOM reads the COLLADA document and places its elements into runtime COLLADA DOM objects. COLLADA DOM objects with registered integration libraries automatically create their associated application data structures.
    2. The COLLADA runtime calls the conversion methods in the integration libraries to convert the content of COLLADA DOM objects into their associated data structures.
  4. When exporting to a COLLADA document:
    1. If COLLADA DOM objects don’t already exist for the COLLADA elements that you want to export, application calls createTo to create them.
    2. Application begins the export of a COLLADA DAE structure by calling save; the COLLADA runtime calls registered conversion methods in the integration libraries to convert the content of the application's data structures into COLLADA DOM objects and then exports the DOM objects to elements in a COLLADA document.

COLLADA DOM Integration Templates

At import time, the DOM loads elements from COLLADA documents into DOM objects in a run-time COLLADA Object Model. The COLLADA DOM provides integration templates to enable you to convert COLLADA data between the DOM objects and your own run-time data structures. ((ELLEN: Note to self: This is redundant from above; consider removing...))

Each DOM object has its own integration template consisting of a header (.h) file and a code (.cpp) file. For example, the DOM object for the COLLADA <node> element is domNode, and the template files to convert domNode objects to or from application data structures are intNode.cpp and intNode.h. ((ANDY: If I got this paragraph right, then I think I need to change the diagram to use domElement1 object and domElementA object (instead of element1 obj and elementA obj)? ))

Copy into your application directory the template files for the elements that you want to convert from DOM objects into application-specific data structures or vice versa. These copies are the starting points for your customized integration libraries. You can then add code to these integration libraries to convert data between DOM objects and their associated application data structures.

The plug-in points for your code are identified in comments in the template source.

The COLLADA DOM provides two sets of integration templates:

  • Simple integration templates: These templates are in the templates/integrationSimple directory, and provide plug-in points for a basic set of COLLADA elements. These templates do not provide plug-in points for nested COLLADA elements, such as the <author> element found in <asset> that is defined by the domAuthor DOM object class.
  • Full integration templates: These templates are in the templates/integrationFull directory, and provide plug-in points for all COLLADA elements.

Integration Objects

Your integration library for each DOM object provides the code that defines an integration object for that object. The integration object serves as the focal point for all information about the conversion. It defines methods that perform the conversion, and it provides data members that bind the DOM object with the application-specific data structure being converted to.

Integration objects are represented with the daeIntegrationObject class. Every class derived from daeElement provides for an integration object through the data member daeElement::_intObject.

The integration object class for each element is defined with the prefix “int”. For example, the domGeometry DAE class provides an intGeometry integration object.

When you define integration code for a DOM object, your code binds the DOM object with your application-specific object, via the _element and _object data members of the integration object. You can use methods daeIntegrationObject::getElement() and getObject() to access these data members.

When you load a COLLADA instance document, the DOM automatically creates the appropriate integration objects.

To get the integration object for an element, use the method daeElement::getIntObject(), which also initiates the conversion process for any objects that have not yet been converted.

Integration Template Plugin Points

The integration class for each DOM object provides six plug-in points into which you can add conversion code. The plug-in points are implemented as methods; you provide the code for the method bodies. You need to implement the body of the methods only for those plug-in points that are relevant to your application.

The methods are:

  • createFrom(): Defines the code to create the application-specific data structure associated with the DAE class for this template. This method sets up the integration object for the DAE class.
  • fromCOLLADA(): Defines the code to covert a DOM object into your application-specific data structure.
  • fromCOLLADAPostProcess(): Defines any postprocessing code that must execute after the basic conversion to your data structure.
  • createTo(): Defines code to create the DOM object associated with the DAE class for this template if such a structure does not already exist (for example, if it was not created while importing).
  • toCOLLADA(): Defines the code to covert the content of your application’s data structures into DOM objects.
  • toCOLLADAPostProcess(): Defines any postprocessing code that must execute after the basic conversion from your application’s data structure.

Geometry Integration Example

This example demonstrates integration with the <geometry> element.

Creating the example has three basic steps, summarized as follows:

  1. Copy the corresponding integration templates to application-specific versions.
  2. Register these classes with the COLLADA DOM.
  3. In the application runtime, add code to initialize the COLLADA DOM, call the file load, and request application objects from the integration classes.

Copying Integration Templates

The first step in the process of creating conversion code is to copy the relevant integration template files from the integration subdirectory into your application’s directory. For this example, the relevant integration templates are intGeometry.cpp and intGeometry.h. You will modify the copied files to contain your conversion code.

Registering Integration Libraries

For the DOM to create integration objects during parsing or before exporting, you must register the integration objects with the infrastructure. To do this, call the registerElement() method on each integration library that you are using. A convenience function to register these classes with the COLLADA DOM is defined in intRegisterElements.cpp, which is also provided in the template directory. You can copy this function into your application’s directory. The relevant code for this example is shown here:

void intRegisterElements()
{
    intGeometry::registerElement();
}

The integration library file provides the definition for the intGeometry class. Its contents are explained in a later step.

After the intRegisterElements() function is defined, pass a handle to this function into the DAE::setIntegrationLibrary() method, as described in the “Invoking Integration Libraries Registration” section.

Setting up the Integration Library Header File

Now edit the new integration library for the objects to be converted. Start with the intGeometry.h integration library copied from the intGeometry.h template. The template must be modified to add information about the application data structures to or from which the DOM object will be converted. For the header, declare the class to be converted into or from:

// class myGeometry is fully defined in an application header file.
class myGeometry;

Also add code to define the relevant structures and provide a method to return those structures. These definitions fall within the body of the intGeometry integration object declaration:

class intGeometry : public daeIntegrationObject
{
    // intGeometry template declarations provided here
    . . .
public: // USER CODE
    virtual ~intGeometry();
    // define the accessor for the myGeometry object
    myGeometry *getGeometry() { return _object; }
private: // USER CODE
    // declare the types for the integration object data members
    myGeometry *_object;
    daeElement *_element;
};

Defining Your Application Data Structure

Within the integration library files, provide the code to create your application-specific data structure for the COLLADA DOM objects that you want to convert.

For this example, the application's data structure used to represent geometry is defined in an application header file, in this case, myGeometry.h:

// Definition of application's myPologon class also included here
class myGeometry
{
public:
    unsigned int _iVertexCount;
    float *_pVertices;
    std::vector<myPolygon> _vPolygons;
};

Provide the Plug-in Code to Create an Application Object for Importing

The plug-in method relevant to this step for importing is the createFrom()' method. Within the createFrom() method, add code to create a new myGeometry object, initialize it, and initialize the intGeometry integration object data members. Within intGeometry.cpp:

void intGeometry::createFrom(daeElementRef element)
{
    // create class to hold geometry information and
    // initialize the new object as empty
    _object = new myGeometry();
    _object->pVertices = NULL;
    // set up the _element data member of the integration object
    _element = element;
}

Now, when a COLLADA instance document is loaded and a domGeometry object is encountered, the createFrom() method automatically creates a new myGeometry object, because the intGeometry integration library has been registered with the DOM.

Build Conversion Code for Importing

Now add code to the integration library to translate the data stored in a DOM object to its associated application data structure. The fromCOLLADA() method is the plug-in point for the basic application-specific conversion code. The fromCOLLADAPostProcess() method provides additional flexibility for the conversion process.

Depending on the COLLADA DOM object and the application data structure, the code may vary significantly. For this example, we use the intGeometry::fromCOLLADA() method to create new vertex buffers from the COLLADA DAE geometry object.

The following code retrieves the mesh object from the COLLADA domGeometry object:

// Get the geometry element from this integration object
domGeometry* geomElement = (domGeometry*)(domElement*)getElement();
domMesh *meshEl = geomElement->getMesh();

When we have the mesh, we can construct our application-specific data structure iVertices for the myGeometry object. The following code shows how to create the new vertex buffer.

// Get a pointer to the application-defined geometry object that was
// automatically created during load by calling createFrom.
myGeometry *local = (myGeometry *)_object;
// Get a pointer to the domPolygons in this domMesh. To simplify this example,
// we will handle only a domMesh that has a single domPolygons.
if(meshElement->getPolygons_array().getCount() != 1)
{
    fprintf(stderr, "This example supports only one domPolygons per domMesh\n");
    return;
}
domPolygons *polygons = meshElement->getPolygons_array()[0];
int polygonCount = polygons->getCount();
// To simplify this example, we assume the domPolygons has only one domInput.
if(polygons->getInput_array().getCount() != 1)
{
    fprintf(stderr, "This example supports only one domInput per domPolygons\n");
    return;
}
// Loop over all the polygons in the domPolygons element
for (int i=0;i<polygonCount;i++)
{
    myPolygon myPoly;
    // Get pointer to this polygon (domP).
    domPolygons::domP *poly = polygons->getP_array()[i];
    // Get the number of indices from the domP and save it in my structure.
    myPoly._iIndexCount = poly->getValue().getCount();
    // You can modify the data as you copy it from
    // the COLLADA object to your object.
    // Here we repeat the first index in list as the last index,
    // to form a closed loop that can be drawn as a line strip.
    myPoly._iIndexCount++;
    myPoly._pIndexes = new unsigned short[myPoly._iIndexCount];
    // Copy all the indices from the domP into my structure.
    for (int j=0;j<myPoly._iIndexCount-1;j++)
    myPoly._pIndexes[j] = poly->getValue()[j];
    // Repeat the first index at the end of the list to create a closed loop.
    myPoly._pIndexes[j] = myPoly._pIndexes[0];
    // Push this polygon into the list of polygons in my structure.
    local->_vPolygons.push_back(myPoly);
}
// Copy the vertices we are going to use into myGeometry. To keep things simple,
// we will assume there is only one domSource and domFloatArray in the domMesh,
// that it is the array of vertices, and that it is in X, Y, Z format. A real
// app would find the vertices by starting with domPolygons and following
// the links through the domInput, domVertices, domSource, domFloat_array,
// and domTechnique.
if(meshElement->getSource_array().getCount() != 1)
{
    fprintf(stderr, "This example supports only one source array per domMesh\n");
    return;
}
domSource *source = meshElement->getSource_array()[0];
if(source->getFloat_array().getCount() != 1)
{
    fprintf(stderr, "This example supports only one float array per source\n");
}
domFloat_array *floatArray = source->getFloat_array()[0];
// Assume there are 3 values per vertex with a stride of 3.
local->_iVertexCount = floatArray->getCount()/3;
local->_pVertices = new float[local->_iVertexCount*3];
// Copy the vertices into my structure one-by-one
// (converts from COLLADA's doubles to floats).
for ( unsigned int i = 0; i < local->_iVertexCount*3; i++ ) 
{
    local->_pVertices[i] = floatArray->getValue()[i];
}

Access COLLADA Objects from the Application

Now put together the application code that registers the integration libraries, loads the COLLADA elements into the in-memory DOM objects, and accesses the converted data.

Invoke Integration Libraries Registration

You defined the intRegisterElements() function as described in “Register Integration Libraries with the DOM.” Now you must pass a handle to this function into the DAE::setIntegrationLibrary() method.

With this step, the elements that you want to convert are registered with the DOM, and are converted from COLLADA DOM objects to application-specific structures when a COLLADA document is loaded, or the reverse when an object is saved.

For example, your main application code could pass a handle to the integration library registration function as follows:

// Instantiate the reference implementation
daeObject = new DAE;
//register the integration objects
daeObject->setIntegrationLibrary(&intRegisterElements);

Parse a COLLADA File

Now parse a COLLADA document into the run-time COLLADA Object Model. The load step creates the integration objects and invokes the createFrom() and romCOLLADA() methods to convert the data from the COLLADA DOM objects into the application-defined data structures.

//load the COLLADA file
int res = daeObject->load(filename);

Access a COLLADA Object

With the COLLADA file parsed and loaded into in-memory objects, you can now request objects from the database ((ELLEN note to self: I've removed previous mentions of the database because seemed not relevant earlier but clearly need somewhere to specify that there is a database into which (something) goes.ANDY: what does the database contain?)). Here we request that the database return the first geometry element, placing it into pElem.

//query the runtime to retrieve an element
int res = daeObject->getDatabase()->getElement
((daeElement**)&pElem,0,NULL,COLLADA_ELEMENT_GEOMETRY);

Acquire the Converted Application Object

In the following code, the myGeometry class represents the application data structure containing geometry data. The COLLADA DOM object retrieved above into pElem contains a reference to its associated integration object (thanks to its earlier registration). The intGeometry class converts the COLLADA data ((ELLEN: which collada data are we talking about here?)) and returns the converted data as a myGeometry instance via the getGeometry()method, which was defined in importGeometry.h.

// Get the integration object from the element
daeIntegrationObject *pIntegrationObj = pElem->getIntObject();
intGeometry *importGeometry =(intGeometry *)pIntegrationObj;
//extract the user data from the integration object
myGeometry geom = importGeometry->getGeometry();

Exporting Using Integration

The preceding sections showed how to set up your integration objects, import a COLLADA instance document, and ensure that the data is converted into data structures specific to your application.

If you modify data values and want to write it to a COLLADA instance document, the process is similar to reversing the import-and-convert process, although there are some differences.

Modifying a COLLADA DOM Object Structure

In some cases, your application might modify the structure of your application objects that you loaded from a COLLADA DOM object. If you want to export the data back to a COLLADA instance document, you must change the structure of the COLLADA DOM object to match your changes before converting from your application-specific structures. The example code does not show how to do this.

Creating a New COLLADA DOM Object Using createTo

In some cases, you might need to export your data to an entirely new COLLADA document, such as when the data originated in your application rather than by being imported from an existing COLLADA instance document. In this cases, to use the integration methods to convert from your application structure to a DOM object and then export to a new COLLADA instance document, you must create the matching COLLADA DOM structure before you can convert from your application’s structure.

Compare with the import process: When your application loads a COLLADA instance document, the COLLADA DOM automatically creates DOM objects in which to load the COLLADA data, then calls your customized createFrom for each element that has an integration class, which creates your application-specific objects. Then it calls fromCOLLADA, which copies the data from the DOM objects to your application objects.

If you create a new application object, there are no COLLADA elements (no DOM objects) associated with it. If you simply save the file, this new data is not written. The purpose of createTo is to create these COLLADA elements and associate them with the application object. createTo is not called automatically when a new application object is created; you must call it explicitly. After createTo has been called, the rest of the saving process is automatic, that is, if you have registered your integration library, when you call save, toCOLLADA is called for every COLLADA element with an integration class to copy the data from the application objects into the COLLADA objects.

This example code does not show how to do this. The createTo method looks like this:

void intGeometry::createTo(void *userData)
{
    // This function would create new COLLADA elements from an
    // application- defined object
    // It is NOT called automatically by the COLLADA DOM.
    // The user needs to call this when creating a new
    // application-specific object.
}

Exporting Modified Data Values

If you have modified only the values of the COLLADA data and want to export to a revised COLLADA instance document, this example shows how you might convert the data.

The saving process for this example is automatic because you have registered your integration library. When you call save, the DOM calls toCOLLADA for every COLLADA element with an integration class. This copies the data from the application objects into the COLLADA ones.

Note that the code is essentially the reverse of the fromCOLLADA code in the importing example.

void intGeometry::toCOLLADA()
{
    // INSERT CODE TO TRANSLATE TO YOUR RUNTIME HERE
    // The following lines are example code from the template:
    // myRuntimeClassType* local = (myRuntimeClassType*)_object;
    // element->foo = local->foo;
    // element->subelem[0]->bar = local->bar;
    // This code takes data from an application-defined object and
    // puts it back into the appropriate collada objects.
    // Get a pointer to the COLLADA domGeometry element
    // (this is the element that called us)
    domGeometry* geometryElement = (domGeometry*)(domElement*)_element;
    // Get a pointer to the domGeometry's domMesh element
    domMesh *meshElement = geometryElement->getMesh();
    // Get a pointer to my object that's assocated with this collada object
    myGeometry *local = (myGeometry *)_object;
    // Get a pointer to the domPolygons in this domMesh.
    // To simplify this example,
    // we will handle only a domMesh that has a single domPolygons
    if(meshElement->getPolygons_array().getCount() != 1)
    {
        fprintf(stderr, "this example supports only one domPolygons per domMesh\n");
        return;
    }
    domPolygons *polygons = meshElement->getPolygons_array()[0];
    int polygonCount = local->_vPolygons.size();
    // To simplify this example, we assume that the domPolygons has
    // only one domInput
    if(polygons->getInput_array().getCount() != 1)
    {
        fprintf(stderr, "this example supports only one domInput per domPolygons\n");
        return;
    }
    // Loop over all the polygons in the domPolygons element and
    // put the data from
    // myGeometry back into it. For the purposes of the example,
    // assume the number of polygons and indices hasn't changed
    // so we can just update the values in place
    polygons->setCount(polygonCount);
    for (int i=0;i<polygonCount;i++)
    {
        // Get pointer to this polygon (domP)
        domPolygons::domP *poly = polygons->getP_array()[i];
        // Copy all the indices from my structure back to the domP
        for (int j=0;j< local->_vPolygons[i]._iIndexCount-1;j++)
            poly->getValue()[j] = local->_vPolygons[i]._pIndexes[j] ;
    }
    // Now copy the vertices from myGeometry back to the source.
    // Assume that the number of
    // vertices hasn't changed so we can just update them in place.
    if(meshElement->getSource_array().getCount() != 1)
    {
        fprintf(stderr, "this example supports only one source array per domMesh\n");
        return;
    }
    domSource *source = meshElement->getSource_array()[0];
    if(source->getFloat_array_array().getCount() != 1)
    {
        fprintf(stderr, "this example supports only one float array per source\n");
    }
    domFloat_array *floatArray = source->getFloat_array()[0];
    // Copy the vertices into from myGeometry back into the
    // COLLADA float array
    floatArray->setCount(local->_iVertexCount*3);
    for ( unsigned int i = 0; i < local->_iVertexCount*3; i++ ) 
    {
        floatArray->getValue()[i] = local->_pVertices[i];
    }
}