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:
@@ -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.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user