Skip to content

Commit

Permalink
fixed: reuse geometry if it there is an instance with the same materi…
Browse files Browse the repository at this point in the history
…al available

git-svn-id: https://opensg.vrsource.org/svn/trunk@2250 4683daeb-ad0f-0410-a623-93161e962ae5
  • Loading branch information
cneumann committed Dec 29, 2009
1 parent 4fd1f69 commit 1376ff8
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 43 deletions.
92 changes: 67 additions & 25 deletions Source/System/FileIO/Collada/OSGColladaGeometry.cpp
Expand Up @@ -96,43 +96,74 @@ 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;

ColladaInstanceGeometryRefPtr colInstGeo =
dynamic_cast<ColladaInstanceGeometry *>(colInstElem);

// XXX TODO - reuse geometry if possible
// - handle <bind_material>

const MaterialMap &matMap = colInstGeo->getMaterialMap();

NodeUnrecPtr groupN = makeCoredNode<Group>();

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<Geometry>(
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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -985,7 +1016,7 @@ ColladaGeometry::mapProperties(
{
if(colInstEffect->findTC(bi->target, mappedProp) == true)
{
OSG_COLLADA_LOG(("ColladaGeometry::mapProperties: "
OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: "
"Resolved <bind> semantic [%s] "
"target [%s] to property [%d]\n",
bi->semantic.c_str(), bi->target.c_str(),
Expand All @@ -998,7 +1029,7 @@ ColladaGeometry::mapProperties(
}
else
{
SWARNING << "ColladaGeometry::mapProperties: "
SWARNING << "ColladaGeometry::handleBindMaterial: "
<< "Failed to resolve <bind> semantic ["
<< bi->semantic << "] target [" << bi->target
<< "]." << std::endl;
Expand All @@ -1008,7 +1039,7 @@ ColladaGeometry::mapProperties(
{
if(colInstEffect->findTC(bvi->semantic, mappedProp) == true)
{
OSG_COLLADA_LOG(("ColladaGeometry::mapProperties: "
OSG_COLLADA_LOG(("ColladaGeometry::handleBindMaterial: "
"Resolved <bind_vertex_input> "
"inSemantic [%s] inSet [%d] semantic [%s] "
"to property [%d]\n",
Expand All @@ -1022,7 +1053,7 @@ ColladaGeometry::mapProperties(
}
else
{
SWARNING << "ColladaGeometry::mapProperties: "
SWARNING << "ColladaGeometry::handleBindMaterial: "
<< "Failed to resolve <bind_vertex_input> "
<< "inSemantic ["
<< bvi->inSemantic << "] inSet [" << bvi->inSet
Expand All @@ -1031,7 +1062,7 @@ ColladaGeometry::mapProperties(
}
}

// find additional consumers
// find next consumers if any
++bindOffset;
++bindVertexOffset;

Expand All @@ -1043,9 +1074,11 @@ ColladaGeometry::mapProperties(

// if the property is not remapped by <bind> or <bind_vertex_input>
// 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 "
"<bind>/<bind_vertex_input> mapping.\n", i));

Expand All @@ -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 <bind> (actually a BindInfo built from a <bind>) that has
the given \a semantic. The search starts at the given \a offset to
allow multiple <bind> with the same semantic to be found.
*/
const ColladaGeometry::BindInfo *
ColladaGeometry::findBind(
const BindStore &store, const std::string &semantic, UInt32 &offset)
Expand All @@ -1085,6 +1122,11 @@ ColladaGeometry::findBind(
return retVal;
}

/*! Returns a <bind_vertex_input> (actually a BindVertexInfo built from
a <bind_vertex_input>) that has the given \a inSemantic and \a inSet.
The search starts at the given \a offset to allow
multiple <bind_vertex_input> with the same inSemantic/inSet to be found.
*/
const ColladaGeometry::BindVertexInfo *
ColladaGeometry::findBindVertex(
const BindVertexStore &store, const std::string &inSemantic,
Expand Down
15 changes: 11 additions & 4 deletions Source/System/FileIO/Collada/OSGColladaGeometry.h
Expand Up @@ -143,6 +143,12 @@ class OSG_FILEIO_DLLMAPPING ColladaGeometry : public ColladaInstantiableElement
typedef std::vector<GeoIntegralPropertyUnrecPtr> IndexStore;
typedef IndexStore::iterator IndexStoreIt;
typedef IndexStore::const_iterator IndexStoreConstIt;

// map <instance_material> target attribute to an index into
// the instance store (getInstStore())
typedef std::map<std::string, UInt32> InstanceMap;
typedef InstanceMap::iterator InstanceMapIt;
typedef InstanceMap::const_iterator InstanceMapConstIt;

struct GeoInfo
{
Expand All @@ -153,13 +159,14 @@ class OSG_FILEIO_DLLMAPPING ColladaGeometry : public ColladaInstantiableElement

GeoIntegralPropertyUnrecPtr _lengths;
GeoIntegralPropertyUnrecPtr _types;

InstanceMap _instMap;
};

typedef std::vector<GeoInfo > GeoStore;
typedef GeoStore::iterator GeoStoreIt;
typedef GeoStore::const_iterator GeoStoreConstIt;


void readMesh (domMesh *mesh);
void readSources (domMesh *mesh);

Expand Down Expand Up @@ -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,
Expand Down
35 changes: 22 additions & 13 deletions Source/System/FileIO/Collada/OSGColladaInstanceMaterial.cpp
Expand Up @@ -65,7 +65,9 @@ ColladaInstanceMaterial::read(void)
{
OSG_COLLADA_LOG(("ColladaInstanceMaterial::read\n"));

ColladaMaterialRefPtr colMat = getSourceElem();
domInstance_materialRef instMat =
getDOMElementAs<domInstance_material>();
ColladaMaterialRefPtr colMat = getSourceElem();

if(colMat == NULL)
{
Expand All @@ -76,8 +78,18 @@ ColladaInstanceMaterial::read(void)
colMat->read();
}

domInstance_materialRef instMat =
getDOMElementAs<domInstance_material>();
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();

Expand Down Expand Up @@ -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 *
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -237,6 +245,7 @@ ColladaInstanceMaterial::ColladaInstanceMaterial(

: Inherited (elem, global)
, _symbol ()
, _target ()
, _bindStore ()
, _bindVertexStore()
{
Expand Down
4 changes: 3 additions & 1 deletion Source/System/FileIO/Collada/OSGColladaInstanceMaterial.h
Expand Up @@ -92,7 +92,7 @@ class OSG_FILEIO_DLLMAPPING ColladaInstanceMaterial

/*! \} */
/*---------------------------------------------------------------------*/
/*! \name Craete */
/*! \name Create */
/*! \{ */

static ColladaElementTransitPtr
Expand All @@ -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 (
Expand Down Expand Up @@ -143,6 +144,7 @@ class OSG_FILEIO_DLLMAPPING ColladaInstanceMaterial
static ColladaElementRegistrationHelper _regHelper;

std::string _symbol;
std::string _target;
BindStore _bindStore;
BindVertexStore _bindVertexStore;
};
Expand Down

0 comments on commit 1376ff8

Please sign in to comment.