Various fixes to the flt loader, and knock on changes to the osgUtil::Optimizer

to better support removal of seperate osg::Geometry instances where they
share the same state and bindings.
This commit is contained in:
Robert Osfield
2002-07-18 00:53:03 +00:00
parent 735b9d2318
commit 09bdb10af5
15 changed files with 609 additions and 230 deletions

View File

@@ -82,9 +82,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
StateVisitor osv;
node->accept(osv);
osv.optimize();
MergeGeometryVisitor mgv;
node->accept(mgv);
#endif
}
@@ -138,7 +140,7 @@ class TransformFunctor : public osg::Drawable::AttributeFunctor
void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode)
{
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::GeoSet* geoset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (geoset)
@@ -204,7 +206,7 @@ void Optimizer::StateVisitor::apply(osg::Geode& geode)
{
osg::StateSet* ss = geode.getStateSet();
if (ss && ss->getDataVariance()==osg::Object::STATIC) addStateSet(ss,&geode);
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::Drawable* drawable = geode.getDrawable(i);
if (drawable)
@@ -385,7 +387,7 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Geode& geode)
osg::Matrix matrix;
if (!_matrixStack.empty()) matrix = _matrixStack.back();
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
// register each drawable with the objectMap.
_objectMap[geode.getDrawable(i)].add(_transformStack,matrix);
@@ -493,7 +495,7 @@ void Optimizer::FlattenStaticTransformsVisitor::doTransform(osg::Object* obj,osg
axis.normalize();
billboard->setAxis(axis);
for(int i=0;i<billboard->getNumDrawables();++i)
for(unsigned int i=0;i<billboard->getNumDrawables();++i)
{
billboard->setPos(i,billboard->getPos(i)*matrix);
billboard->getDrawable(i)->applyAttributeOperation(tf);
@@ -650,7 +652,7 @@ void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Geode& geode)
osg::Matrix matrix;
if (!_matrixStack.empty()) matrix = _matrixStack.back();
for(int i=0;i<geode.getNumDrawables();++i)
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
// register each drawable with the objectMap.
_objectMap[geode.getDrawable(i)].add(transform,matrix);
@@ -755,7 +757,7 @@ void Optimizer::RemoveLowestStaticTransformsVisitor::doTransform(osg::Object* ob
axis.normalize();
billboard->setAxis(axis);
for(int i=0;i<billboard->getNumDrawables();++i)
for(unsigned int i=0;i<billboard->getNumDrawables();++i)
{
billboard->setPos(i,billboard->getPos(i)*matrix);
billboard->getDrawable(i)->applyAttributeOperation(tf);
@@ -1162,3 +1164,166 @@ void Optimizer::CombineLODsVisitor::combineLODs()
_groupList.clear();
}
////////////////////////////////////////////////////////////////////////////
// code to merge geometry object which share, state, and attribute bindings.
////////////////////////////////////////////////////////////////////////////
struct LessGeometry
{
bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs)
{
if (lhs->getStateSet()<rhs->getStateSet()) return true;
if (rhs->getStateSet()<lhs->getStateSet()) return false;
if (lhs->getColorBinding()<rhs->getColorBinding()) return true;
if (rhs->getColorBinding()<lhs->getColorBinding()) return false;
if (lhs->getNormalBinding()<rhs->getNormalBinding()) return true;
if (rhs->getNormalBinding()<lhs->getNormalBinding()) return false;
if (lhs->getNumTexCoordArrays()<rhs->getNumTexCoordArrays()) return true;
if (rhs->getNumTexCoordArrays()<lhs->getNumTexCoordArrays()) return false;
// therefore lhs->getNumTexCoordArrays()==rhs->getNumTexCoordArrays()
for(unsigned int i=0;i<lhs->getNumTexCoordArrays();++i)
{
if (rhs->getTexCoordArray(i))
{
if (!lhs->getTexCoordArray(i)) return true;
}
else if (lhs->getTexCoordArray(i)) return false;
}
if (lhs->getNormalBinding()==osg::Geometry::BIND_OVERALL)
{
// assumes that the bindings and arrays are set up correctly, this
// should be the case after running computeCorrectBindingsAndArraySizes();
const osg::Vec3& lhs_normal = (*(lhs->getNormalArray()))[0];
const osg::Vec3& rhs_normal = (*(rhs->getNormalArray()))[0];
if (lhs_normal<rhs_normal) return true;
if (rhs_normal<lhs_normal) return false;
}
if (lhs->getColorBinding()==osg::Geometry::BIND_OVERALL)
{
if (lhs->getColorArray()->getType()<rhs->getColorArray()->getType()) return true;
if (rhs->getColorArray()->getType()<lhs->getColorArray()->getType()) return false;
}
return false;
}
};
bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode)
{
if (geode.getNumDrawables()<2) return false;
typedef std::vector<osg::Geometry*> DuplicateList;
typedef std::map<osg::Geometry*,DuplicateList,LessGeometry> GeometryDuplicateMap;
GeometryDuplicateMap geometryDuplicateMap;
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
if (geom)
{
geom->computeCorrectBindingsAndArraySizes();
geometryDuplicateMap[geom].push_back(geom);
}
}
for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin();
itr!=geometryDuplicateMap.end();
++itr)
{
if (itr->second.size()>1)
{
osg::Geometry* lhs = itr->second[0];
for(DuplicateList::iterator dupItr=itr->second.begin()+1;
dupItr!=itr->second.end();
++dupItr)
{
osg::Geometry* rhs = *dupItr;
if (mergeGeometry(*lhs,*rhs))
{
geode.removeDrawable(rhs);
static int co = 0;
osg::notify(osg::INFO)<<"merged and removed Geometry "<<++co<<std::endl;
}
}
}
}
return false;
}
bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs)
{
unsigned int base = 0;
if (lhs.getVertexArray() && rhs.getVertexArray())
{
base = lhs.getVertexArray()->size();
lhs.getVertexArray()->insert(lhs.getVertexArray()->end(),rhs.getVertexArray()->begin(),rhs.getVertexArray()->end());
}
else if (rhs.getVertexArray())
{
lhs.setVertexArray(rhs.getVertexArray());
}
if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalBinding()!=osg::Geometry::BIND_OVERALL)
{
lhs.getNormalArray()->insert(lhs.getNormalArray()->end(),rhs.getNormalArray()->begin(),rhs.getNormalArray()->end());
}
else if (rhs.getNormalArray())
{
lhs.setNormalArray(rhs.getNormalArray());
}
if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL)
{
// we need to add the handling of the other array types...
osg::Vec4Array* col_lhs = dynamic_cast<osg::Vec4Array*>(lhs.getColorArray());
osg::Vec4Array* col_rhs = dynamic_cast<osg::Vec4Array*>(rhs.getColorArray());
if (col_lhs && col_rhs)
{
col_lhs->insert(col_lhs->end(),col_rhs->begin(),col_rhs->end());
}
}
else if (rhs.getColorArray())
{
lhs.setColorArray(rhs.getColorArray());
}
for(unsigned int unit=0;unit<lhs.getNumTexCoordArrays();++unit)
{
// we need to add the handling of the other array types...
osg::Vec2Array* tex_lhs = dynamic_cast<osg::Vec2Array*>(lhs.getTexCoordArray(unit));
osg::Vec2Array* tex_rhs = dynamic_cast<osg::Vec2Array*>(rhs.getTexCoordArray(unit));
if (tex_lhs && tex_rhs)
{
tex_lhs->insert(tex_lhs->end(),tex_rhs->begin(),tex_rhs->end());
}
}
// shift the indices of the incomming primitives to account for the pre exisiting geometry.
for(osg::Geometry::PrimitiveList::iterator primItr=rhs.getPrimitiveList().begin();
primItr!=rhs.getPrimitiveList().end();
++primItr)
{
osg::Primitive* primitive = primItr->get();
primitive->offsetIndices(base);
}
lhs.getPrimitiveList().insert(lhs.getPrimitiveList().end(),rhs.getPrimitiveList().begin(),rhs.getPrimitiveList().end());
return true;
}