Added conversion to osg::GeoSet::converToGeometry() utility to help the

migration to and testing of the new osg::Geometry class.
This commit is contained in:
Robert Osfield
2002-06-23 21:43:46 +00:00
parent bbc129e5c6
commit f2e215bf44
10 changed files with 1022 additions and 88 deletions

View File

@@ -4,6 +4,8 @@
#include <osg/LOD>
#include <osg/Impostor>
#include <osg/Billboard>
#include <osg/Geometry>
#include <osg/GeoSet>
#include <osg/Notify>
#include <typeinfo>
@@ -18,6 +20,7 @@ using namespace osgUtil;
void Optimizer::optimize(osg::Node* node, unsigned int options)
{
if (options & COMBINE_ADJACENT_LODS)
{
CombineLODsVisitor clv;
@@ -30,15 +33,42 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
FlattenStaticTransformsVisitor fstv;
node->accept(fstv);
fstv.removeTransforms();
// the following RemoveLowestStaticTransformVisitor doesn't yet work
// properly, will need further work.... Robert Osfield, June 2002.
// int i=0;
// bool result = false;
// do
// {
// cout << "************ RemoveLowestStaticTransformsVisitor "<<i<<endl;
// RemoveLowestStaticTransformsVisitor fstv;
// node->accept(fstv);
// result = fstv.removeTransforms();
// ++i;
// } while (result);
}
if (options & REMOVE_REDUNDENT_NODES)
{
RemoveEmptyNodesVisitor renv;
node->accept(renv);
renv.removeEmptyNodes();
RemoveRedundentNodesVisitor rrnv;
node->accept(rrnv);
rrnv.removeRedundentNodes();
}
// // convert the old style GeoSet to Geometry
// ConvertGeoSetsToGeometryVisitor cgtg;
// node->accept(cgtg);
if (options & SHARE_DUPLICATE_STATE)
{
#if (defined(_MSC_VER) && _MSC_VER<1300 && !defined(_STLPORT_VERSION))
@@ -50,6 +80,9 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
#endif
}
}
class TransformFunctor : public osg::Drawable::AttributeFunctor
@@ -94,6 +127,34 @@ class TransformFunctor : public osg::Drawable::AttributeFunctor
};
////////////////////////////////////////////////////////////////////////////
// Convert GeoSet To Geometry Visitor.
////////////////////////////////////////////////////////////////////////////
void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode)
{
for(int i=0;i<geode.getNumDrawables();++i)
{
osg::GeoSet* geoset = dynamic_cast<osg::GeoSet*>(geode.getDrawable(i));
if (geoset)
{
osg::Geometry* geom = geoset->convertToGeometry();
if (geom)
{
std::cout<<"Successfully converted GeoSet to Geometry"<<std::endl;
geode.replaceDrawable(geoset,geom);
}
else
{
std::cout<<"*** Failed to convert GeoSet to Geometry"<<std::endl;
}
}
}
}
////////////////////////////////////////////////////////////////////////////
// Optimize State Visitor
////////////////////////////////////////////////////////////////////////////
@@ -153,7 +214,6 @@ void Optimizer::StateVisitor::optimize()
{
osg::notify(osg::INFO) << "Num of StateSet="<<_statesets.size()<< std::endl;
{
// create map from state attributes to stateset which contain them.
typedef std::set<osg::StateSet*> StateSetList;
@@ -335,13 +395,18 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Transform& transform)
}
else
{
osg::ref_ptr<osg::Matrix> matrix = osgNew osg::Matrix;
osg::ref_ptr<osg::Matrix> matrix;
if (_matrixStack.empty())
{
matrix = osgNew osg::Matrix;
}
else
{
matrix = osgNew osg::Matrix(_matrixStack.back());
}
transform.getLocalToWorldMatrix(*matrix,this);
if (!_matrixStack.empty())
{
matrix->postMult(_matrixStack.back());
}
_matrixStack.push_back(*matrix);
_transformStack.push_back(&transform);
@@ -523,8 +588,6 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms()
{
if (titr->second._canBeApplied)
{
osg::ref_ptr<osg::Transform> transform = titr->first;
osg::ref_ptr<osg::Group> group = osgNew osg::Group;
group->setDataVariance(osg::Object::STATIC);
@@ -548,6 +611,342 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms()
_matrixStack.clear();
}
////////////////////////////////////////////////////////////////////////////
// Flatten static transforms
////////////////////////////////////////////////////////////////////////////
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Geode& geode)
{
osg::Transform* transform = NULL;
if (!_transformStack.back()) transform = _transformStack.back();
osg::Matrix matrix;
if (!_matrixStack.empty()) matrix = _matrixStack.back();
for(int i=0;i<geode.getNumDrawables();++i)
{
// register each drawable with the objectMap.
_objectMap[geode.getDrawable(i)].add(transform,matrix);
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Billboard& billboard)
{
if (!_matrixStack.empty())
{
// register ourselves with the objectMap.
_objectMap[&billboard].add(_transformStack.back(),_matrixStack.back());
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::LOD& lod)
{
if (!_matrixStack.empty())
{
// register ourselves with the objectMap.
_objectMap[&lod].add(_transformStack.back(),_matrixStack.back());
}
traverse(lod);
}
void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Transform& transform)
{
if (_ignoreDynamicTransforms && transform.getDataVariance()==osg::Object::DYNAMIC)
{
// simple traverse the children as if this Transform didn't exist.
traverse(transform);
}
else
{
if (!_matrixStack.empty())
{
_transformMap[&transform]._containsTransform=false;
}
osg::Matrix matrix;
transform.getLocalToWorldMatrix(matrix,this);
_matrixStack.push_back(matrix);
_transformStack.push_back(&transform);
// simple traverse the children as if this Transform didn't exist.
traverse(transform);
_transformStack.pop_back();
_matrixStack.pop_back();
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::doTransform(osg::Object* obj,osg::Matrix& matrix)
{
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(obj);
if (drawable)
{
TransformFunctor tf(matrix);
drawable->applyAttributeOperation(tf);
drawable->dirtyBound();
return;
}
osg::LOD* lod = dynamic_cast<osg::LOD*>(obj);
if (lod)
{
osg::Matrix matrix_no_trans = matrix;
matrix_no_trans.setTrans(0.0f,0.0f,0.0f);
osg::Vec3 v111(1.0f,1.0f,1.0f);
osg::Vec3 new_v111 = v111*matrix_no_trans;
float ratio = new_v111.length()/v111.length();
// move center point.
lod->setCenter(lod->getCenter()*matrix);
// adjust ranges to new scale.
for(unsigned int i=0;i<lod->getNumRanges();++i)
{
lod->setRange(i,lod->getRange(i)*ratio);
}
lod->dirtyBound();
return;
}
osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(obj);
if (billboard)
{
osg::Matrix matrix_no_trans = matrix;
matrix_no_trans.setTrans(0.0f,0.0f,0.0f);
TransformFunctor tf(matrix_no_trans);
osg::Vec3 axis = osg::Matrix::transform3x3(tf._im,billboard->getAxis());
axis.normalize();
billboard->setAxis(axis);
for(int i=0;i<billboard->getNumDrawables();++i)
{
billboard->setPos(i,billboard->getPos(i)*matrix);
billboard->getDrawable(i)->applyAttributeOperation(tf);
}
billboard->dirtyBound();
return;
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::disableObject(ObjectMap::iterator itr)
{
if (itr==_objectMap.end())
{
// Euston we have a problem..
osg::notify(osg::WARN)<<"Warning: internal error Optimizer::RemoveLowestStaticTransformsVisitor::disableObject()"<<std::endl;
return;
}
if (itr->second._canBeApplied)
{
// we havn't been disabled yet so we need to disable,
itr->second._canBeApplied = false;
// and then inform everybody we have been disabled.
for(ObjectStruct::TransformSet::iterator titr = itr->second._transformSet.begin();
titr != itr->second._transformSet.end();
++titr)
{
disableTransform(*titr);
}
}
}
void Optimizer::RemoveLowestStaticTransformsVisitor::disableTransform(osg::Transform* transform)
{
TransformMap::iterator itr=_transformMap.find(transform);
if (itr==_transformMap.end())
{
// Euston we have a problem..
osg::notify(osg::WARN)<<"Warning: internal error Optimizer::RemoveLowestStaticTransformsVisitor::disableTransform()"<<std::endl;
return;
}
if (itr->second._canBeApplied)
{
// we havn'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();
oitr != itr->second._objectSet.end();
++oitr)
{
disableObject(*oitr);
}
}
}
bool Optimizer::RemoveLowestStaticTransformsVisitor::removeTransforms()
{
// create the TransformMap from the ObjectMap
ObjectMap::iterator oitr;
for(oitr=_objectMap.begin();
oitr!=_objectMap.end();
++oitr)
{
osg::Object* object = oitr->first;
ObjectStruct& os = oitr->second;
for(ObjectStruct::TransformSet::iterator titr = os._transformSet.begin();
titr != os._transformSet.end();
++titr)
{
_transformMap[*titr].add(object);
}
}
for(TransformMap::iterator titr=_transformMap.begin();
titr!=_transformMap.end();
++titr)
{
TransformStruct& ts = titr->second;
if (ts._containsTransform)
{
disableTransform(titr->first);
}
}
// disable all the objects which have more than one matrix associated
// with them, and then disable all transforms which have an object associated
// them that can't be applied, and then disable all objects which have
// disabled transforms associated, recursing until all disabled
// associativity.
for(oitr=_objectMap.begin();
oitr!=_objectMap.end();
++oitr)
{
ObjectStruct& os = oitr->second;
if (os._canBeApplied)
{
if (os._moreThanOneMatrixRequired)
{
disableObject(oitr);
}
}
}
// transform the objects that can be applied.
for(oitr=_objectMap.begin();
oitr!=_objectMap.end();
++oitr)
{
osg::Object* object = oitr->first;
ObjectStruct& os = oitr->second;
if (os._canBeApplied)
{
doTransform(object,os._matrix);
}
}
bool transformsRemoved = false;
// clean up the transforms.
for(TransformMap::iterator titr=_transformMap.begin();
titr!=_transformMap.end();
++titr)
{
if (titr->second._canBeApplied && titr->first)
{
osg::ref_ptr<osg::Transform> transform = titr->first;
osg::ref_ptr<osg::Group> group = osgNew osg::Group;
group->setDataVariance(osg::Object::STATIC);
for(unsigned int i=0;i<transform->getNumChildren();++i)
{
for(unsigned int j=0;j<transform->getNumParents();++j)
{
group->addChild(transform->getChild(i));
}
}
for(int i2=transform->getNumParents()-1;i2>=0;--i2)
{
transform->getParent(i2)->replaceChild(transform.get(),group.get());
}
transformsRemoved = true;
}
}
_objectMap.clear();
_transformMap.clear();
_transformStack.clear();
_matrixStack.clear();
return transformsRemoved;
}
////////////////////////////////////////////////////////////////////////////
// RemoveEmptyNodes.
////////////////////////////////////////////////////////////////////////////
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Geode& geode)
{
if (geode.getNumParents()>0)
{
if (geode.getNumDrawables()==0) _redundentNodeList.insert(&geode);
}
}
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group)
{
if (group.getNumParents()>0)
{
if (group.getNumChildren()==0)
{
_redundentNodeList.insert(&group);
}
}
traverse(group);
}
void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes()
{
NodeList newEmptyGroups;
// keep iterator through until scene graph is cleaned of empty nodes.
while (!_redundentNodeList.empty())
{
for(NodeList::iterator itr=_redundentNodeList.begin();
itr!=_redundentNodeList.end();
++itr)
{
osg::Node* nodeToRemove = (*itr);
// take a copy of parents list since subsequent removes will modify the original one.
osg::Node::ParentList parents = nodeToRemove->getParents();
for(osg::Node::ParentList::iterator pitr=parents.begin();
pitr!=parents.end();
++pitr)
{
(*pitr)->removeChild(nodeToRemove);
if ((*pitr)->getNumChildren()==0) newEmptyGroups.insert(*pitr);
}
}
_redundentNodeList.clear();
_redundentNodeList.swap(newEmptyGroups);
}
}
////////////////////////////////////////////////////////////////////////////
// RemoveRedundentNodes.
@@ -555,24 +954,42 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms()
void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Group& group)
{
if (typeid(group)==typeid(osg::Group))
if (group.getNumParents()>0)
{
if (group.getNumParents()>0 && group.getNumChildren()<=1)
if (group.getNumChildren()==1 && typeid(group)==typeid(osg::Group))
{
if (!group.getUserData() &&
!group.getAppCallback() &&
!group.getStateSet() &&
group.getNodeMask()==0xffffffff)
if (group.getNumParents()>0 && group.getNumChildren()<=1)
{
_redundentNodeList.insert(&group);
if (!group.getUserData() &&
!group.getAppCallback() &&
!group.getStateSet() &&
group.getNodeMask()==0xffffffff)
{
_redundentNodeList.insert(&group);
}
}
}
}
traverse(group);
}
void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Transform& transform)
{
if (transform.getNumParents()>0)
{
static osg::Matrix identity;
if (transform.getMatrix()==identity && transform.getDataVariance()==osg::Object::STATIC)
{
_redundentNodeList.insert(&transform);
}
}
traverse(transform);
}
void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
{
for(NodeList::iterator itr=_redundentNodeList.begin();
itr!=_redundentNodeList.end();
++itr)
@@ -582,17 +999,8 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
{
// take a copy of parents list since subsequent removes will modify the original one.
osg::Node::ParentList parents = group->getParents();
if (group->getNumChildren()==0)
{
for(osg::Node::ParentList::iterator pitr=parents.begin();
pitr!=parents.end();
++pitr)
{
(*pitr)->removeChild(group.get());
}
}
else if (group->getNumChildren()==1)
if (group->getNumChildren()==1)
{
osg::Node* child = group->getChild(0);
for(osg::Node::ParentList::iterator pitr=parents.begin();
@@ -601,14 +1009,13 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
{
(*pitr)->replaceChild(group.get(),child);
}
}
else // (group->getNumChildren()>1)
{
osg::notify(osg::WARN)<<"Warning: Optimizer::RemoveRedundentNodesVisitor has incorrectly assigned Group to remove."<<std::endl;
osg::notify(osg::WARN)<<" Safely ignoring remove operation for this group."<<std::endl;
}
}
else
{
std::cout<<"failed dynamic_cast"<<endl;
}
}
_redundentNodeList.clear();
@@ -616,7 +1023,6 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes()
////////////////////////////////////////////////////////////////////////////
// combine LOD's.
////////////////////////////////////////////////////////////////////////////