From 1376ff8699e363355cf200520d5253f89d33139e Mon Sep 17 00:00:00 2001 From: cneumann Date: Tue, 29 Dec 2009 23:38:23 +0000 Subject: [PATCH] fixed: reuse geometry if it there is an instance with the same material available git-svn-id: https://opensg.vrsource.org/svn/trunk@2250 4683daeb-ad0f-0410-a623-93161e962ae5 --- .../FileIO/Collada/OSGColladaGeometry.cpp | 92 ++++++++++++++----- .../FileIO/Collada/OSGColladaGeometry.h | 15 ++- .../Collada/OSGColladaInstanceMaterial.cpp | 35 ++++--- .../Collada/OSGColladaInstanceMaterial.h | 4 +- 4 files changed, 103 insertions(+), 43 deletions(-) diff --git a/Source/System/FileIO/Collada/OSGColladaGeometry.cpp b/Source/System/FileIO/Collada/OSGColladaGeometry.cpp index 8631a928b..1b3e79698 100644 --- a/Source/System/FileIO/Collada/OSGColladaGeometry.cpp +++ b/Source/System/FileIO/Collada/OSGColladaGeometry.cpp @@ -96,7 +96,7 @@ ColladaGeometry::read(void) Node * ColladaGeometry::createInstance(ColladaInstanceElement *colInstElem) { - SWARNING << "ColladaGeometry::createInstance: NIY" << std::endl; + OSG_COLLADA_LOG(("ColladaGeometry::createInstance\n")); typedef ColladaInstanceGeometry::MaterialMap MaterialMap; typedef ColladaInstanceGeometry::MaterialMapConstIt MaterialMapConstIt; @@ -104,35 +104,66 @@ ColladaGeometry::createInstance(ColladaInstanceElement *colInstElem) ColladaInstanceGeometryRefPtr colInstGeo = dynamic_cast(colInstElem); - // XXX TODO - reuse geometry if possible - // - handle - const MaterialMap &matMap = colInstGeo->getMaterialMap(); - NodeUnrecPtr groupN = makeCoredNode(); - GeoStoreConstIt gsIt = _geoStore.begin(); - GeoStoreConstIt gsEnd = _geoStore.end (); + // 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()); - GeometryUnrecPtr geo = Geometry::create(); - NodeUnrecPtr geoN = makeNodeFor(geo); - - getGlobal()->getStatCollector()->getElem( - ColladaGlobal::statNGeometryCreated)->inc(); + // 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->setLengths(gsIt->_lengths); - geo->setTypes (gsIt->_types ); + geo = dynamic_pointer_cast( + getInstStore()[instIt->second]); + } + else + { + // create new geometry + + geo = Geometry::create(); + + getGlobal()->getStatCollector()->getElem( + ColladaGlobal::statNGeometryCreated)->inc(); - mapProperties(*gsIt, geo, colInstGeo); + 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); } - // XXX TODO: do we need to always generate a new geo? + // store the generated group node editInstStore().push_back(groupN); return groupN; @@ -924,7 +955,7 @@ ColladaGeometry::setupGeometry(const domInputLocal_Array &vertInputs, } void -ColladaGeometry::mapProperties( +ColladaGeometry::handleBindMaterial( const GeoInfo &geoInfo, Geometry *geo, ColladaInstanceGeometry *colInstGeo) { typedef ColladaInstanceGeometry::MaterialMap MaterialMap; @@ -944,7 +975,7 @@ ColladaGeometry::mapProperties( } else { - SWARNING << "ColladaGeometry::mapProperties: No material found " + SWARNING << "ColladaGeometry::handleBindMaterial: No material found " << "for symbol [" << geoInfo._matSymbol << "]." << std::endl; } @@ -985,7 +1016,7 @@ ColladaGeometry::mapProperties( { if(colInstEffect->findTC(bi->target, mappedProp) == true) { - OSG_COLLADA_LOG(("ColladaGeometry::mapProperties: " + OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: " "Resolved semantic [%s] " "target [%s] to property [%d]\n", bi->semantic.c_str(), bi->target.c_str(), @@ -998,7 +1029,7 @@ ColladaGeometry::mapProperties( } else { - SWARNING << "ColladaGeometry::mapProperties: " + SWARNING << "ColladaGeometry::handleBindMaterial: " << "Failed to resolve semantic [" << bi->semantic << "] target [" << bi->target << "]." << std::endl; @@ -1008,7 +1039,7 @@ ColladaGeometry::mapProperties( { if(colInstEffect->findTC(bvi->semantic, mappedProp) == true) { - OSG_COLLADA_LOG(("ColladaGeometry::mapProperties: " + OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: " "Resolved " "inSemantic [%s] inSet [%d] semantic [%s] " "to property [%d]\n", @@ -1022,7 +1053,7 @@ ColladaGeometry::mapProperties( } else { - SWARNING << "ColladaGeometry::mapProperties: " + SWARNING << "ColladaGeometry::handleBindMaterial: " << "Failed to resolve " << "inSemantic [" << bvi->inSemantic << "] inSet [" << bvi->inSet @@ -1031,7 +1062,7 @@ ColladaGeometry::mapProperties( } } - // find additional consumers + // find next consumers if any ++bindOffset; ++bindVertexOffset; @@ -1043,9 +1074,11 @@ ColladaGeometry::mapProperties( // if the property is not remapped by or // we just put it at the location it received at read time + // this is for properties that are not of interest to the material + // directly (e.g. positions, normals) if(handledProperty == false) { - OSG_COLLADA_LOG(("ColladaGeometry::mapProperties: " + OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: " "Setting property [%d] without " "/ mapping.\n", i)); @@ -1060,12 +1093,16 @@ ColladaGeometry::mapProperties( } else { - SWARNING << "ColladaGeometry::mapProperties: No material created " + SWARNING << "ColladaGeometry::handleBindMaterial: No material created " << "for symbol [" << geoInfo._matSymbol << "]." << std::endl; } } +/*! Returns a (actually a BindInfo built from a ) that has + the given \a semantic. The search starts at the given \a offset to + allow multiple with the same semantic to be found. + */ const ColladaGeometry::BindInfo * ColladaGeometry::findBind( const BindStore &store, const std::string &semantic, UInt32 &offset) @@ -1085,6 +1122,11 @@ ColladaGeometry::findBind( return retVal; } +/*! Returns a (actually a BindVertexInfo built from + a ) that has the given \a inSemantic and \a inSet. + The search starts at the given \a offset to allow + multiple with the same inSemantic/inSet to be found. + */ const ColladaGeometry::BindVertexInfo * ColladaGeometry::findBindVertex( const BindVertexStore &store, const std::string &inSemantic, diff --git a/Source/System/FileIO/Collada/OSGColladaGeometry.h b/Source/System/FileIO/Collada/OSGColladaGeometry.h index 0deebde5f..7cef159f7 100644 --- a/Source/System/FileIO/Collada/OSGColladaGeometry.h +++ b/Source/System/FileIO/Collada/OSGColladaGeometry.h @@ -143,6 +143,12 @@ class OSG_FILEIO_DLLMAPPING ColladaGeometry : public ColladaInstantiableElement typedef std::vector IndexStore; typedef IndexStore::iterator IndexStoreIt; typedef IndexStore::const_iterator IndexStoreConstIt; + + // map target attribute to an index into + // the instance store (getInstStore()) + typedef std::map InstanceMap; + typedef InstanceMap::iterator InstanceMapIt; + typedef InstanceMap::const_iterator InstanceMapConstIt; struct GeoInfo { @@ -153,13 +159,14 @@ class OSG_FILEIO_DLLMAPPING ColladaGeometry : public ColladaInstantiableElement GeoIntegralPropertyUnrecPtr _lengths; GeoIntegralPropertyUnrecPtr _types; + + InstanceMap _instMap; }; typedef std::vector GeoStore; typedef GeoStore::iterator GeoStoreIt; typedef GeoStore::const_iterator GeoStoreConstIt; - void readMesh (domMesh *mesh); void readSources (domMesh *mesh); @@ -187,9 +194,9 @@ class OSG_FILEIO_DLLMAPPING ColladaGeometry : public ColladaInstantiableElement xsNCName matSymbold, IndexStore &indexStore ); - void mapProperties(const GeoInfo &geoInfo, - Geometry *geo, - ColladaInstanceGeometry *colInstGeo); + void handleBindMaterial(const GeoInfo &geoInfo, + Geometry *geo, + ColladaInstanceGeometry *colInstGeo); const BindInfo *findBind (const BindStore &store, const std::string &semantic, diff --git a/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.cpp b/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.cpp index 147b4dbee..fb3a419fd 100644 --- a/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.cpp +++ b/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.cpp @@ -65,7 +65,9 @@ ColladaInstanceMaterial::read(void) { OSG_COLLADA_LOG(("ColladaInstanceMaterial::read\n")); - ColladaMaterialRefPtr colMat = getSourceElem(); + domInstance_materialRef instMat = + getDOMElementAs(); + ColladaMaterialRefPtr colMat = getSourceElem(); if(colMat == NULL) { @@ -76,8 +78,18 @@ ColladaInstanceMaterial::read(void) colMat->read(); } - domInstance_materialRef instMat = - getDOMElementAs(); + if(instMat->getSymbol() != NULL) + { + _symbol = instMat->getSymbol(); + } + else + { + SFATAL << "ColladaInstanceMaterial::read: No symbol." + << std::endl; + } + + _target = instMat->getTarget().str(); + const domInstance_material::domBind_Array &binds = instMat->getBind_array(); @@ -121,16 +133,6 @@ ColladaInstanceMaterial::read(void) _bindVertexStore[i].inSemantic = inSemantic; _bindVertexStore[i].inSet = inSet; } - - if(instMat->getSymbol() != NULL) - { - _symbol = instMat->getSymbol(); - } - else - { - SFATAL << "ColladaInstanceMaterial::read: No symbol." - << std::endl; - } } Material * @@ -175,6 +177,12 @@ ColladaInstanceMaterial::getSymbol(void) const return _symbol; } +const std::string & +ColladaInstanceMaterial::getTarget(void) const +{ + return _target; +} + const ColladaInstanceMaterial::BindStore & ColladaInstanceMaterial::getBindStore(void) const { @@ -237,6 +245,7 @@ ColladaInstanceMaterial::ColladaInstanceMaterial( : Inherited (elem, global) , _symbol () + , _target () , _bindStore () , _bindVertexStore() { diff --git a/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.h b/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.h index b0d10642a..b2a8004af 100644 --- a/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.h +++ b/Source/System/FileIO/Collada/OSGColladaInstanceMaterial.h @@ -92,7 +92,7 @@ class OSG_FILEIO_DLLMAPPING ColladaInstanceMaterial /*! \} */ /*---------------------------------------------------------------------*/ - /*! \name Craete */ + /*! \name Create */ /*! \{ */ static ColladaElementTransitPtr @@ -115,6 +115,7 @@ class OSG_FILEIO_DLLMAPPING ColladaInstanceMaterial virtual domMaterial *getSourceDOMElem (void) const; const std::string &getSymbol (void) const; + const std::string &getTarget (void) const; const BindStore &getBindStore (void ) const; const BindInfo *findBindInfo ( @@ -143,6 +144,7 @@ class OSG_FILEIO_DLLMAPPING ColladaInstanceMaterial static ColladaElementRegistrationHelper _regHelper; std::string _symbol; + std::string _target; BindStore _bindStore; BindVertexStore _bindVertexStore; };