DOM guide: Representing elements in the object model: Difference between revisions
No edit summary |
m (fix spec links) |
||
Line 7: | Line 7: | ||
===Element Object Names=== | ===Element Object Names=== | ||
Every element defined in the [[COLLADA | Every element defined in the [[COLLADA Specification]] maps onto a corresponding <code>dom*</code> class, which is derived from the <code>daeElement</code> class. The [[code generator]] used to create the C++ classes creates the name of the class based on the element’s XML type. Most elements in COLLADA use an XML tag that is the same as their type. For example, the <code><camera></code> element maps onto the <code>domCamera</code> class, the <code><bool_array></code> element maps onto the <code>domBool_array</code> class, and the <code><source></code> element maps on the <code>domSource</code> class. However, some element's names are different from their types; for example, the <code><xfov></code> element maps to the <code>domTargettableFloat</code> class and the <code><instance_visual_scene></code> element maps to the <code>domInstanceWithExtra</code> class. | ||
===Attributes=== | ===Attributes=== | ||
Attributes of the element map onto data members of the <code>dom*</code> object. For example, the <code><geometry></code> element as defined in the COLLADA | Attributes of the element map onto data members of the <code>dom*</code> object. For example, the <code><geometry></code> element as defined in the COLLADA Specification includes two attributes, ''id'' and ''name''. The <code>domGeometry</code> class includes <code>attrName</code> and <code>attrId</code> data members for the attributes. | ||
===Child elements=== | ===Child elements=== | ||
Children of the element map into data members that are typed to match the type of the child element. When an element can have multiple children of the same type, the data member is an array. For example, the <code><geometry></code> element as defined in the COLLADA | Children of the element map into data members that are typed to match the type of the child element. When an element can have multiple children of the same type, the data member is an array. For example, the <code><geometry></code> element as defined in the COLLADA Specification can have one <code><mesh></code> child and any number of <code><extra></code> elements as children. The <code>domGeometry</code> class provides an <code>elemMesh</code> data member to hold the object’s <code>domMesh</code> child and an <code>elemExtra_array</code> to hold any number of <code>domExtra</code> child elements. | ||
==Reference Counting Classes== | ==Reference Counting Classes== |
Latest revision as of 01:55, 10 December 2008
The COLLADA Object Model is a set of objects that correspond to elements in a COLLADA XML instance document (a COLLADA document). This article describes what these objects look like and how an application can manipulate them.
Representation of COLLADA Object Model Elements
After an application loads a COLLADA document so that the DOM has created equivalent objects in the COLLADA Object Model, the structure of COLLADA Object Model objects closely matches the element structure found in the original COLLADA document.
Note: The DOM does not perfectly preserve the structure of the original COLLADA instance document; some pieces of information that don’t affect the interpretation of the file may be rearranged. This means that, if an application uses the DOM to read a COLLADA document and immediately write it back out without making any changes, the documents may not be identical, though they will be functionally equivalent. You may notice differences in the order of attributes within an XML tag, or in the precision or output format of floating-point numbers. If an optional attribute is set to its default value, that attribute is suppressed when writing to the output document.
Element Object Names
Every element defined in the COLLADA Specification maps onto a corresponding dom*
class, which is derived from the daeElement
class. The code generator used to create the C++ classes creates the name of the class based on the element’s XML type. Most elements in COLLADA use an XML tag that is the same as their type. For example, the <camera>
element maps onto the domCamera
class, the <bool_array>
element maps onto the domBool_array
class, and the <source>
element maps on the domSource
class. However, some element's names are different from their types; for example, the <xfov>
element maps to the domTargettableFloat
class and the <instance_visual_scene>
element maps to the domInstanceWithExtra
class.
Attributes
Attributes of the element map onto data members of the dom*
object. For example, the <geometry>
element as defined in the COLLADA Specification includes two attributes, id and name. The domGeometry
class includes attrName
and attrId
data members for the attributes.
Child elements
Children of the element map into data members that are typed to match the type of the child element. When an element can have multiple children of the same type, the data member is an array. For example, the <geometry>
element as defined in the COLLADA Specification can have one <mesh>
child and any number of <extra>
elements as children. The domGeometry
class provides an elemMesh
data member to hold the object’s domMesh
child and an elemExtra_array
to hold any number of domExtra
child elements.
Reference Counting Classes
To facilitate tracking of dom* objects within the DOM, the DOM uses reference counting classes that correspond to each dom*
class. The daeSmartRef<T>
class template is used to define reference counting objects for daeElement
subclasses. So, for example, the definition:
typedef daeSmartRef<domCOLLADA> domCOLLADARef;
defines domCOLLADARef
, which is a reference counted domCOLLADA
object. Every dom*
class provides one of these reference counting classes. In most cases you do not need to use the domCOLLADARef
reference directly; however, whenever a daeElement
is placed into the tree using the daeElement::createAndPlace
method (described in the following “Adding and Removing Elements” section), the DOM creates the reference counted version of the object.
Note: The DOM makes extensive use of the daeElementRef
reference counting classes. If you use a creation method that returns a daeElementRef
(such as those in daeMetaElement
), be sure to receive the return value into a daeElementRef
rather than into a dom*
element class pointer. If the value is not returned into a daeElementRef
, it can result in incorrect reference counting, which may cause the object to immediately try and delete itself, leaving a pointer to uninitialized memory. Generally you will not want to change the reference count of an object on your own; avoid calling the daeElement::ref
or release
methods.
Casting Types Using daeSafeCast
The COLLADA DOM provides a C++-style cast operator to safely downcast daeElement
and daeElementRef
to their strongly-typed dom* equivalent:
template <typename T> inline T *daeSafeCast( daeElement *element )
Many functions in the DOM return a reference to the base class daeElement
and you must then cast the reference to its specific type for further use. For example:
domInstanceGeometry *instance_geometry; //retrieved from a domNode element domGeometry *geometry = daeSafeCast< domGeometry >( instance_geometry->getUrl().getElement() );
The daeSafeCast
operator returns NULL if the element provided does not match the type specified.
Working with daeTArrays
The DOM uses the templated class daeTArray
object as the base class for many of the data members of objects derived from the daeElement
class. It is used to represent the links between a parent and a child and to hold lists of other types of data. When you work with a daeTArray
object, you need to use different methods to manipulate the array depending on what type of data the array contains.
daeTArrays containing daeElements
When a daeTArray
contains something derived from a daeElement
, such as a domInput_Array
, domParam_Array
, or domP_Array
:
- To add elements to the array, call
daeElement::createAndPlace
on the daeElement containing thedaeTArray
. - To explicitly place an element at a specific position within the array of child elements, use
daeElement::createAndPlaceAt
, which does the same thing asdaeElement::createAndPlace
, but places the element at a specific index in the daeTArray. - To remove elements from the array, use
daeElement::removeChildElement
.
daeTArrays containing other objects
When a daeTArray
contains something other than an object derived from daeElement
:
- To append a new array element, use the
daeTArray::append
method. - To append the array element only if it doesn’t already exist in the array, use the
daeTArray::appendUnique
method. - To insert a new element at a specific index within the array, use the
daeTArray::insertAt
method, which grows the array if necessary. - To change the value of a specific index, use the
daeTArray::set
method. - To remove an array element, use the
daeTArray::remove
method to remove the array element by value, ordaeTArray::removeIndex
to remove the array element at a specific index.
Example
The following example shows how to add data to both types of arrays. In this example, tristrips
is a pointer to domTristrips
, and we want to add a new triangle strip to its elemP_array
. The content of the elemP_array
is derived from a daeElement
, while the _value
array in the elemP_array
is a simple list of integers.
// Add a new <p> element. Use createAndPlace because domP is derived from daeElement. // This adds a new element to domTristrips::elemP_array. domP* p = daeSafeCast<domP>(tristrips->createAndPlace("p")); // Then use daeTArray::append to add indices to the domP::_value array, which is a list of domUint. p->getValue().append3(1, 2, 3); tristrips->setCount(1);
Note: The count data field found in some DOM objects, such as domTristrips, domPolygons, domTriangles, domAccessor, or domFloat_Array
, is not updated automatically when you call createAndPlace or removeChildElement
. For example, if you change the number of elements in the elemP_array
of a domTristrips
, you need to update the count data member yourself. That's the reason for the last line in the previous code excerpt.
Setting and retrieving daeTArray data
The daeTArray
class contains many functions to help with the manipulation of arrays of data. These functions include set2, set3, set4, append2, append3, append4, get2, get3, get4
, and so on.
To get the data from either type of array, use the get
or index operator[]
and getCount
methods. You can also use the find
method to find a specific value within the array.
The following example shows iterating through the polygon groups on a mesh. The object thisMesh
is a pointer to domMesh
.
int polygonCnt = thisMesh->getPolygons_array().getCount(); for (int currPoly = 0; currPoly < polygonCnt; currPoly++) { domPolygons *thisPoly = thisMesh->getPolygons_array().get(currPoly); … }
Caution: Do not use the daeArray::clear
method on any array whose contents are daeElement objects (e.g. domTristrips::elemP_array). This method does not update the _contents
array of the containing object, so while it may appear to delete data, the data may still be written to the COLLADA instance document when the database is saved.
COLLADA DOM - Version 2.4 Historical Reference |
---|
List of main articles under the DOM portal. |
User Guide chapters: • Intro • Architecture • Setting up • Working with documents • Creating docs • Importing docs • Representing elements • Working with elements • Resolving URIs • Resolving SIDs • Using custom COLLADA data • Integration templates • Error handling Systems: • URI resolver • Meta • Load/save flow • Runtime database • Memory • StringRef • Code generator |