mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 18:59:57 +00:00
Update optimizer with upstream improvements
This commit is contained in:
parent
0ab0e6ef93
commit
de572226e4
1 changed files with 70 additions and 136 deletions
|
@ -422,7 +422,7 @@ void CollectLowestTransformsVisitor::disableObject(ObjectMap::iterator itr)
|
|||
|
||||
if (itr->second._canBeApplied)
|
||||
{
|
||||
// we havn't been disabled yet so we need to disable,
|
||||
// we haven't been disabled yet so we need to disable,
|
||||
itr->second._canBeApplied = false;
|
||||
|
||||
// and then inform everybody we have been disabled.
|
||||
|
@ -446,7 +446,7 @@ void CollectLowestTransformsVisitor::disableTransform(osg::Transform* transform)
|
|||
if (itr->second._canBeApplied)
|
||||
{
|
||||
|
||||
// we havn't been disabled yet so we need to disable,
|
||||
// we haven't been disabled yet so we need to disable,
|
||||
itr->second._canBeApplied = false;
|
||||
// and then inform everybody we have been disabled.
|
||||
for(TransformStruct::ObjectSet::iterator oitr = itr->second._objectSet.begin();
|
||||
|
@ -905,7 +905,7 @@ void Optimizer::RemoveRedundantNodesVisitor::removeRedundantNodes()
|
|||
|
||||
struct LessGeometry
|
||||
{
|
||||
bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) const
|
||||
bool operator() (const osg::ref_ptr<osg::Geometry>& lhs,const osg::ref_ptr<osg::Geometry>& rhs) const
|
||||
{
|
||||
if (lhs->getStateSet()<rhs->getStateSet()) return true;
|
||||
if (rhs->getStateSet()<lhs->getStateSet()) return false;
|
||||
|
@ -1001,7 +1001,7 @@ struct LessGeometry
|
|||
|
||||
struct LessGeometryPrimitiveType
|
||||
{
|
||||
bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) const
|
||||
bool operator() (const osg::ref_ptr<osg::Geometry>& lhs,const osg::ref_ptr<osg::Geometry>& rhs) const
|
||||
{
|
||||
for(unsigned int i=0;
|
||||
i<lhs->getNumPrimitiveSets() && i<rhs->getNumPrimitiveSets();
|
||||
|
@ -1115,26 +1115,22 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
if (group.getNumChildren()>=2)
|
||||
{
|
||||
|
||||
typedef std::vector<osg::Geometry*> DuplicateList;
|
||||
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
|
||||
typedef std::map<osg::Geometry*,DuplicateList,LessGeometry> GeometryDuplicateMap;
|
||||
typedef std::vector< osg::ref_ptr<osg::Geometry> > DuplicateList;
|
||||
typedef std::vector< osg::ref_ptr<osg::Node> > Nodes;
|
||||
typedef std::map< osg::ref_ptr<osg::Geometry> ,DuplicateList,LessGeometry> GeometryDuplicateMap;
|
||||
|
||||
typedef std::vector<DuplicateList> MergeList;
|
||||
|
||||
GeometryDuplicateMap geometryDuplicateMap;
|
||||
DrawableList standardDrawables;
|
||||
Nodes standardChildren;
|
||||
|
||||
unsigned int i;
|
||||
for(i=0;i<group.getNumChildren();++i)
|
||||
{
|
||||
osg::Drawable* drawable = group.getChild(i)->asDrawable();
|
||||
if (drawable)
|
||||
{
|
||||
osg::Geometry* geom = drawable->asGeometry();
|
||||
osg::Node* child = group.getChild(i);
|
||||
osg::Geometry* geom = child->asGeometry();
|
||||
if (geom)
|
||||
{
|
||||
//geom->computeCorrectBindingsAndArraySizes();
|
||||
|
||||
if (!geometryContainsSharedArrays(*geom) &&
|
||||
geom->getDataVariance()!=osg::Object::DYNAMIC &&
|
||||
isOperationPermissibleForObject(geom))
|
||||
|
@ -1143,17 +1139,15 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
}
|
||||
else
|
||||
{
|
||||
standardDrawables.push_back(drawable);
|
||||
standardChildren.push_back(geom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
standardDrawables.push_back(drawable);
|
||||
}
|
||||
standardChildren.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
// first try to group geometries with the same properties
|
||||
// (i.e. array types) to avoid loss of data during merging
|
||||
MergeList mergeListChecked; // List of drawables just before merging, grouped by "compatibility" and vertex limit
|
||||
|
@ -1183,7 +1177,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
dupItr!=itr->second.end();
|
||||
++dupItr)
|
||||
{
|
||||
osg::Geometry* geomToPush = *dupItr;
|
||||
osg::Geometry* geomToPush = dupItr->get();
|
||||
|
||||
// try to group geomToPush with another geometry
|
||||
MergeList::iterator eachMergeList=mergeListTmp.begin();
|
||||
|
@ -1216,126 +1210,74 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
// then build merge list using _targetMaximumNumberOfVertices
|
||||
bool needToDoMerge = false;
|
||||
// dequeue each DuplicateList when vertices limit is reached or when all elements has been checked
|
||||
for(;!mergeListChecked.empty();)
|
||||
for(MergeList::iterator itr=mergeListChecked.begin(); itr!=mergeListChecked.end(); ++itr)
|
||||
{
|
||||
MergeList::iterator itr=mergeListChecked.begin();
|
||||
DuplicateList& duplicateList(*itr);
|
||||
if (duplicateList.size()==0)
|
||||
{
|
||||
mergeListChecked.erase(itr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (duplicateList.size()==1)
|
||||
{
|
||||
mergeList.push_back(duplicateList);
|
||||
mergeListChecked.erase(itr);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int numVertices(duplicateList.front()->getVertexArray() ? duplicateList.front()->getVertexArray()->getNumElements() : 0);
|
||||
DuplicateList::iterator eachGeom(duplicateList.begin()+1);
|
||||
// until all geometries have been checked or _targetMaximumNumberOfVertices is reached
|
||||
for(;eachGeom!=duplicateList.end(); ++eachGeom)
|
||||
unsigned int totalNumberVertices = 0;
|
||||
DuplicateList subset;
|
||||
for(DuplicateList::iterator ditr = duplicateList.begin();
|
||||
ditr != duplicateList.end();
|
||||
++ditr)
|
||||
{
|
||||
unsigned int numAddVertices((*eachGeom)->getVertexArray() ? (*eachGeom)->getVertexArray()->getNumElements() : 0);
|
||||
if ((numVertices+numAddVertices)>_targetMaximumNumberOfVertices)
|
||||
osg::Geometry* geometry = ditr->get();
|
||||
unsigned int numVertices = (geometry->getVertexArray() ? geometry->getVertexArray()->getNumElements() : 0);
|
||||
if ((totalNumberVertices+numVertices)>_targetMaximumNumberOfVertices && !subset.empty())
|
||||
{
|
||||
break;
|
||||
mergeList.push_back(subset);
|
||||
subset.clear();
|
||||
totalNumberVertices = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
numVertices += numAddVertices;
|
||||
}
|
||||
}
|
||||
|
||||
// push back if bellow the limit
|
||||
if (eachGeom==duplicateList.end())
|
||||
{
|
||||
if (duplicateList.size()>1) needToDoMerge = true;
|
||||
mergeList.push_back(duplicateList);
|
||||
mergeListChecked.erase(itr);
|
||||
}
|
||||
// else split the list to store what is below the limit and retry on what is above
|
||||
else
|
||||
{
|
||||
mergeList.push_back(DuplicateList());
|
||||
DuplicateList* duplicateListResult = &mergeList.back();
|
||||
duplicateListResult->insert(duplicateListResult->end(),duplicateList.begin(),eachGeom);
|
||||
duplicateList.erase(duplicateList.begin(),eachGeom);
|
||||
if (duplicateListResult->size()>1) needToDoMerge = true;
|
||||
totalNumberVertices += numVertices;
|
||||
subset.push_back(geometry);
|
||||
if (subset.size()>1) needToDoMerge = true;
|
||||
}
|
||||
if (!subset.empty()) mergeList.push_back(subset);
|
||||
}
|
||||
|
||||
if (needToDoMerge)
|
||||
{
|
||||
// to avoid performance issues associated with incrementally removing a large number children, we remove them all and add back the ones we need.
|
||||
group.removeChildren(0, group.getNumChildren());
|
||||
|
||||
for(Nodes::iterator itr = standardChildren.begin();
|
||||
itr != standardChildren.end();
|
||||
++itr)
|
||||
{
|
||||
group.addChild(*itr);
|
||||
}
|
||||
|
||||
// now do the merging of geometries
|
||||
for(MergeList::iterator mitr = mergeList.begin();
|
||||
mitr != mergeList.end();
|
||||
++mitr)
|
||||
{
|
||||
DuplicateList& duplicateList = *mitr;
|
||||
if (duplicateList.size()>1)
|
||||
if (!duplicateList.empty())
|
||||
{
|
||||
osg::Geometry* lhs = duplicateList.front();
|
||||
for(DuplicateList::iterator ditr = duplicateList.begin()+1;
|
||||
DuplicateList::iterator ditr = duplicateList.begin();
|
||||
osg::ref_ptr<osg::Geometry> lhs = *ditr++;
|
||||
group.addChild(lhs.get());
|
||||
for(;
|
||||
ditr != duplicateList.end();
|
||||
++ditr)
|
||||
{
|
||||
mergeGeometry(*lhs,**ditr);
|
||||
|
||||
group.removeChild(*ditr);
|
||||
mergeGeometry(*lhs, **ditr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
// don't merge geometry if its above a maximum number of vertices.
|
||||
for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin();
|
||||
itr!=geometryDuplicateMap.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->second.size()>1)
|
||||
{
|
||||
std::sort(itr->second.begin(),itr->second.end(),LessGeometryPrimitiveType());
|
||||
osg::Geometry* lhs = itr->second[0];
|
||||
for(DuplicateList::iterator dupItr=itr->second.begin()+1;
|
||||
dupItr!=itr->second.end();
|
||||
++dupItr)
|
||||
{
|
||||
|
||||
osg::Geometry* rhs = *dupItr;
|
||||
|
||||
if (lhs->getVertexArray() && lhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices)
|
||||
{
|
||||
lhs = rhs;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rhs->getVertexArray() && rhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lhs->getVertexArray() && rhs->getVertexArray() &&
|
||||
(lhs->getVertexArray()->getNumElements()+rhs->getVertexArray()->getNumElements())>=_targetMaximumNumberOfVertices)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mergeGeometry(*lhs,*rhs))
|
||||
{
|
||||
geode.removeDrawable(rhs);
|
||||
|
||||
static int co = 0;
|
||||
OSG_INFO<<"merged and removed Geometry "<<++co<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1580,21 +1522,18 @@ class MergeArrayVisitor : public osg::ArrayVisitor
|
|||
{
|
||||
protected:
|
||||
osg::Array* _lhs;
|
||||
int _offset;
|
||||
public:
|
||||
MergeArrayVisitor() :
|
||||
_lhs(0),
|
||||
_offset(0) {}
|
||||
_lhs(0) {}
|
||||
|
||||
|
||||
/// try to merge the content of two arrays.
|
||||
bool merge(osg::Array* lhs,osg::Array* rhs, int offset=0)
|
||||
bool merge(osg::Array* lhs,osg::Array* rhs)
|
||||
{
|
||||
if (lhs==0 || rhs==0) return true;
|
||||
if (lhs->getType()!=rhs->getType()) return false;
|
||||
|
||||
_lhs = lhs;
|
||||
_offset = offset;
|
||||
|
||||
rhs->accept(*this);
|
||||
return true;
|
||||
|
@ -1607,30 +1546,24 @@ class MergeArrayVisitor : public osg::ArrayVisitor
|
|||
lhs->insert(lhs->end(),rhs.begin(),rhs.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void _mergeAndOffset(T& rhs)
|
||||
{
|
||||
T* lhs = static_cast<T*>(_lhs);
|
||||
|
||||
typename T::iterator itr;
|
||||
for(itr = rhs.begin();
|
||||
itr != rhs.end();
|
||||
++itr)
|
||||
{
|
||||
lhs->push_back(*itr + _offset);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(osg::Array&) { OSG_WARN << "Warning: Optimizer's MergeArrayVisitor cannot merge Array type." << std::endl; }
|
||||
|
||||
virtual void apply(osg::ByteArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
||||
virtual void apply(osg::ShortArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
||||
virtual void apply(osg::IntArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
||||
virtual void apply(osg::UByteArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
||||
virtual void apply(osg::UShortArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
||||
virtual void apply(osg::UIntArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
||||
|
||||
virtual void apply(osg::ByteArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::ShortArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::IntArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::UByteArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::UShortArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::UIntArray& rhs) { _merge(rhs); }
|
||||
|
||||
virtual void apply(osg::Vec4ubArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec3ubArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec2ubArray& rhs) { _merge(rhs); }
|
||||
|
||||
virtual void apply(osg::Vec4usArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec3usArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec2usArray& rhs) { _merge(rhs); }
|
||||
|
||||
virtual void apply(osg::FloatArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec2Array& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec3Array& rhs) { _merge(rhs); }
|
||||
|
@ -1644,6 +1577,7 @@ class MergeArrayVisitor : public osg::ArrayVisitor
|
|||
virtual void apply(osg::Vec2bArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec3bArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec4bArray& rhs) { _merge(rhs); }
|
||||
|
||||
virtual void apply(osg::Vec2sArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec3sArray& rhs) { _merge(rhs); }
|
||||
virtual void apply(osg::Vec4sArray& rhs) { _merge(rhs); }
|
||||
|
|
Loading…
Reference in a new issue