void
ColladaNode::readInstanceGeometry(domInstance_geometry *instGeo)
{
    ColladaInstanceGeometryRefPtr colInstGeo =
        getUserDataAs<ColladaInstanceGeometry>(instGeo);

    if(colInstGeo == NULL)
    {
        colInstGeo = dynamic_pointer_cast<ColladaInstanceGeometry>(
            ColladaElementFactory::the()->create(instGeo, getGlobal()));

        colInstGeo->read(this);
    }
}
void
ColladaNode::handleInstanceGeometry(domInstance_geometry *instGeo)
{
    ColladaInstanceGeometryRefPtr colInstGeo =
        getUserDataAs<ColladaInstanceGeometry>(instGeo);

    if(colInstGeo == NULL)
    {
        colInstGeo = dynamic_pointer_cast<ColladaInstanceGeometry>(
            ColladaElementFactory::the()->create(instGeo, getGlobal()));

        colInstGeo->read();
    }

    NodeUnrecPtr geoN = colInstGeo->process(this);

    appendChild(geoN);
}
Node *
ColladaGeometry::createInstance(ColladaInstInfo *colInstInfo)
{
    typedef ColladaInstanceGeometry::MaterialMap        MaterialMap;
    typedef ColladaInstanceGeometry::MaterialMapConstIt MaterialMapConstIt;

    domGeometryRef geometry = getDOMElementAs<domGeometry>();
    NodeUnrecPtr   groupN   = makeCoredNode<Group>();

    OSG_COLLADA_LOG(("ColladaGeometry::createInstance id [%s]\n",
                     geometry->getId()));

    if(getGlobal()->getOptions()->getCreateNameAttachments() == true &&
       geometry->getName()                                   != NULL   )
    {
        setName(groupN, geometry->getName());
    }

    ColladaInstanceGeometryRefPtr  colInstGeo =
        dynamic_cast<ColladaInstanceGeometry *>(colInstInfo->getColInst());
    const MaterialMap             &matMap     =
        colInstGeo->getMaterialMap();

    // iterate over all parts of geometry
    GeoStoreIt gsIt   = _geoStore.begin();
    GeoStoreIt gsEnd  = _geoStore.end  ();

    for(; gsIt != gsEnd; ++gsIt)
    {
        OSG_ASSERT(gsIt->_propStore.size() == gsIt->_indexStore.size());

        // find the material associated with the geometry's material symbol
        MaterialMapConstIt mmIt       = matMap.find(gsIt->_matSymbol);
        std::string        matTarget;

        if(mmIt != matMap.end())
        {
            matTarget = mmIt->second->getTarget();
        }

        // check if the geometry was already used with that material

        GeometryUnrecPtr   geo      = NULL;
        InstanceMapConstIt instIt   = gsIt->_instMap.find(matTarget);

        if(instIt != gsIt->_instMap.end())
        {
            // reuse geometry

            geo = dynamic_pointer_cast<Geometry>(
                getInstStore()[instIt->second]);

            getGlobal()->getStatCollector()->getElem(
                ColladaGlobal::statNGeometryUsed)->inc();
        }
        else
        {
            // create new geometry

            geo = Geometry::create();

            getGlobal()->getStatCollector()->getElem(
                ColladaGlobal::statNGeometryCreated)->inc();

            geo->setLengths(gsIt->_lengths);
            geo->setTypes  (gsIt->_types  );

            handleBindMaterial(*gsIt, geo, colInstGeo);

            // record the instantiation of the geometry with the
            // material for reuse
            gsIt->_instMap.insert(
                InstanceMap::value_type(matTarget, getInstStore().size()));

            editInstStore().push_back(geo);
        }

        NodeUnrecPtr geoN = makeNodeFor(geo);

        groupN->addChild(geoN);
    }

    // store the generated group node
    editInstStore().push_back(groupN);

    return groupN;
}