mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-26 17:41:33 +00:00
Merge pull request #2259 from Capostrophic/optimizer
Update optimizer with upstream improvements
This commit is contained in:
commit
bafc67dcdb
1 changed files with 70 additions and 136 deletions
|
@ -422,7 +422,7 @@ void CollectLowestTransformsVisitor::disableObject(ObjectMap::iterator itr)
|
||||||
|
|
||||||
if (itr->second._canBeApplied)
|
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;
|
itr->second._canBeApplied = false;
|
||||||
|
|
||||||
// and then inform everybody we have been disabled.
|
// and then inform everybody we have been disabled.
|
||||||
|
@ -446,7 +446,7 @@ void CollectLowestTransformsVisitor::disableTransform(osg::Transform* transform)
|
||||||
if (itr->second._canBeApplied)
|
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;
|
itr->second._canBeApplied = false;
|
||||||
// and then inform everybody we have been disabled.
|
// and then inform everybody we have been disabled.
|
||||||
for(TransformStruct::ObjectSet::iterator oitr = itr->second._objectSet.begin();
|
for(TransformStruct::ObjectSet::iterator oitr = itr->second._objectSet.begin();
|
||||||
|
@ -905,7 +905,7 @@ void Optimizer::RemoveRedundantNodesVisitor::removeRedundantNodes()
|
||||||
|
|
||||||
struct LessGeometry
|
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 (lhs->getStateSet()<rhs->getStateSet()) return true;
|
||||||
if (rhs->getStateSet()<lhs->getStateSet()) return false;
|
if (rhs->getStateSet()<lhs->getStateSet()) return false;
|
||||||
|
@ -1001,7 +1001,7 @@ struct LessGeometry
|
||||||
|
|
||||||
struct LessGeometryPrimitiveType
|
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;
|
for(unsigned int i=0;
|
||||||
i<lhs->getNumPrimitiveSets() && i<rhs->getNumPrimitiveSets();
|
i<lhs->getNumPrimitiveSets() && i<rhs->getNumPrimitiveSets();
|
||||||
|
@ -1115,45 +1115,39 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
||||||
if (group.getNumChildren()>=2)
|
if (group.getNumChildren()>=2)
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef std::vector<osg::Geometry*> DuplicateList;
|
typedef std::vector< osg::ref_ptr<osg::Geometry> > DuplicateList;
|
||||||
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
|
typedef std::vector< osg::ref_ptr<osg::Node> > Nodes;
|
||||||
typedef std::map<osg::Geometry*,DuplicateList,LessGeometry> GeometryDuplicateMap;
|
typedef std::map< osg::ref_ptr<osg::Geometry> ,DuplicateList,LessGeometry> GeometryDuplicateMap;
|
||||||
|
|
||||||
typedef std::vector<DuplicateList> MergeList;
|
typedef std::vector<DuplicateList> MergeList;
|
||||||
|
|
||||||
GeometryDuplicateMap geometryDuplicateMap;
|
GeometryDuplicateMap geometryDuplicateMap;
|
||||||
DrawableList standardDrawables;
|
Nodes standardChildren;
|
||||||
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for(i=0;i<group.getNumChildren();++i)
|
for(i=0;i<group.getNumChildren();++i)
|
||||||
{
|
{
|
||||||
osg::Drawable* drawable = group.getChild(i)->asDrawable();
|
osg::Node* child = group.getChild(i);
|
||||||
if (drawable)
|
osg::Geometry* geom = child->asGeometry();
|
||||||
|
if (geom)
|
||||||
{
|
{
|
||||||
osg::Geometry* geom = drawable->asGeometry();
|
if (!geometryContainsSharedArrays(*geom) &&
|
||||||
if (geom)
|
geom->getDataVariance()!=osg::Object::DYNAMIC &&
|
||||||
|
isOperationPermissibleForObject(geom))
|
||||||
{
|
{
|
||||||
//geom->computeCorrectBindingsAndArraySizes();
|
geometryDuplicateMap[geom].push_back(geom);
|
||||||
|
|
||||||
if (!geometryContainsSharedArrays(*geom) &&
|
|
||||||
geom->getDataVariance()!=osg::Object::DYNAMIC &&
|
|
||||||
isOperationPermissibleForObject(geom))
|
|
||||||
{
|
|
||||||
geometryDuplicateMap[geom].push_back(geom);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
standardDrawables.push_back(drawable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
standardDrawables.push_back(drawable);
|
standardChildren.push_back(geom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
standardChildren.push_back(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
// first try to group geometries with the same properties
|
// first try to group geometries with the same properties
|
||||||
// (i.e. array types) to avoid loss of data during merging
|
// (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
|
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!=itr->second.end();
|
||||||
++dupItr)
|
++dupItr)
|
||||||
{
|
{
|
||||||
osg::Geometry* geomToPush = *dupItr;
|
osg::Geometry* geomToPush = dupItr->get();
|
||||||
|
|
||||||
// try to group geomToPush with another geometry
|
// try to group geomToPush with another geometry
|
||||||
MergeList::iterator eachMergeList=mergeListTmp.begin();
|
MergeList::iterator eachMergeList=mergeListTmp.begin();
|
||||||
|
@ -1216,126 +1210,74 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
||||||
// then build merge list using _targetMaximumNumberOfVertices
|
// then build merge list using _targetMaximumNumberOfVertices
|
||||||
bool needToDoMerge = false;
|
bool needToDoMerge = false;
|
||||||
// dequeue each DuplicateList when vertices limit is reached or when all elements has been checked
|
// 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);
|
DuplicateList& duplicateList(*itr);
|
||||||
if (duplicateList.size()==0)
|
if (duplicateList.size()==0)
|
||||||
{
|
{
|
||||||
mergeListChecked.erase(itr);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duplicateList.size()==1)
|
if (duplicateList.size()==1)
|
||||||
{
|
{
|
||||||
mergeList.push_back(duplicateList);
|
mergeList.push_back(duplicateList);
|
||||||
mergeListChecked.erase(itr);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int numVertices(duplicateList.front()->getVertexArray() ? duplicateList.front()->getVertexArray()->getNumElements() : 0);
|
unsigned int totalNumberVertices = 0;
|
||||||
DuplicateList::iterator eachGeom(duplicateList.begin()+1);
|
DuplicateList subset;
|
||||||
// until all geometries have been checked or _targetMaximumNumberOfVertices is reached
|
for(DuplicateList::iterator ditr = duplicateList.begin();
|
||||||
for(;eachGeom!=duplicateList.end(); ++eachGeom)
|
ditr != duplicateList.end();
|
||||||
|
++ditr)
|
||||||
{
|
{
|
||||||
unsigned int numAddVertices((*eachGeom)->getVertexArray() ? (*eachGeom)->getVertexArray()->getNumElements() : 0);
|
osg::Geometry* geometry = ditr->get();
|
||||||
if ((numVertices+numAddVertices)>_targetMaximumNumberOfVertices)
|
unsigned int numVertices = (geometry->getVertexArray() ? geometry->getVertexArray()->getNumElements() : 0);
|
||||||
|
if ((totalNumberVertices+numVertices)>_targetMaximumNumberOfVertices && !subset.empty())
|
||||||
{
|
{
|
||||||
break;
|
mergeList.push_back(subset);
|
||||||
}
|
subset.clear();
|
||||||
else
|
totalNumberVertices = 0;
|
||||||
{
|
|
||||||
numVertices += numAddVertices;
|
|
||||||
}
|
}
|
||||||
|
totalNumberVertices += numVertices;
|
||||||
|
subset.push_back(geometry);
|
||||||
|
if (subset.size()>1) needToDoMerge = true;
|
||||||
}
|
}
|
||||||
|
if (!subset.empty()) mergeList.push_back(subset);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needToDoMerge)
|
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
|
// now do the merging of geometries
|
||||||
for(MergeList::iterator mitr = mergeList.begin();
|
for(MergeList::iterator mitr = mergeList.begin();
|
||||||
mitr != mergeList.end();
|
mitr != mergeList.end();
|
||||||
++mitr)
|
++mitr)
|
||||||
{
|
{
|
||||||
DuplicateList& duplicateList = *mitr;
|
DuplicateList& duplicateList = *mitr;
|
||||||
if (duplicateList.size()>1)
|
if (!duplicateList.empty())
|
||||||
{
|
{
|
||||||
osg::Geometry* lhs = duplicateList.front();
|
DuplicateList::iterator ditr = duplicateList.begin();
|
||||||
for(DuplicateList::iterator ditr = duplicateList.begin()+1;
|
osg::ref_ptr<osg::Geometry> lhs = *ditr++;
|
||||||
|
group.addChild(lhs.get());
|
||||||
|
for(;
|
||||||
ditr != duplicateList.end();
|
ditr != duplicateList.end();
|
||||||
++ditr)
|
++ditr)
|
||||||
{
|
{
|
||||||
mergeGeometry(*lhs,**ditr);
|
mergeGeometry(*lhs, **ditr);
|
||||||
|
|
||||||
group.removeChild(*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:
|
protected:
|
||||||
osg::Array* _lhs;
|
osg::Array* _lhs;
|
||||||
int _offset;
|
|
||||||
public:
|
public:
|
||||||
MergeArrayVisitor() :
|
MergeArrayVisitor() :
|
||||||
_lhs(0),
|
_lhs(0) {}
|
||||||
_offset(0) {}
|
|
||||||
|
|
||||||
|
|
||||||
/// try to merge the content of two arrays.
|
/// 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==0 || rhs==0) return true;
|
||||||
if (lhs->getType()!=rhs->getType()) return false;
|
if (lhs->getType()!=rhs->getType()) return false;
|
||||||
|
|
||||||
_lhs = lhs;
|
_lhs = lhs;
|
||||||
_offset = offset;
|
|
||||||
|
|
||||||
rhs->accept(*this);
|
rhs->accept(*this);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1607,30 +1546,24 @@ class MergeArrayVisitor : public osg::ArrayVisitor
|
||||||
lhs->insert(lhs->end(),rhs.begin(),rhs.end());
|
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::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::ByteArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::IntArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
virtual void apply(osg::ShortArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::UByteArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
virtual void apply(osg::IntArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::UShortArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _merge(rhs); }
|
virtual void apply(osg::UByteArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::UIntArray& rhs) { if (_offset) _mergeAndOffset(rhs); else _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::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::FloatArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::Vec2Array& rhs) { _merge(rhs); }
|
virtual void apply(osg::Vec2Array& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::Vec3Array& 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::Vec2bArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::Vec3bArray& rhs) { _merge(rhs); }
|
virtual void apply(osg::Vec3bArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::Vec4bArray& rhs) { _merge(rhs); }
|
virtual void apply(osg::Vec4bArray& rhs) { _merge(rhs); }
|
||||||
|
|
||||||
virtual void apply(osg::Vec2sArray& rhs) { _merge(rhs); }
|
virtual void apply(osg::Vec2sArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::Vec3sArray& rhs) { _merge(rhs); }
|
virtual void apply(osg::Vec3sArray& rhs) { _merge(rhs); }
|
||||||
virtual void apply(osg::Vec4sArray& rhs) { _merge(rhs); }
|
virtual void apply(osg::Vec4sArray& rhs) { _merge(rhs); }
|
||||||
|
|
Loading…
Reference in a new issue