From b1f69a9b11ee745d5cd357a8245b1a8eb050cb3e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 30 Aug 2002 15:07:10 +0000 Subject: [PATCH] Fixed the flatten static transform visitor. --- include/osgUtil/Optimizer | 168 +---------- src/osgUtil/Optimizer.cpp | 570 +++++++++++++++----------------------- 2 files changed, 240 insertions(+), 498 deletions(-) diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index 3c0c20cfc..907f9e8c4 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -65,176 +66,33 @@ class OSGUTIL_EXPORT Optimizer - FlattenStaticTransformsVisitor(bool ignoreDynamicTransforms=true): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _ignoreDynamicTransforms(ignoreDynamicTransforms) {} + FlattenStaticTransformsVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} virtual void apply(osg::Geode& geode); - virtual void apply(osg::Billboard& billboard); - virtual void apply(osg::LOD& lod); - virtual void apply(osg::Transform& transform); - - void removeTransforms(); - - - typedef std::vector TransformStack; - typedef std::vector MatrixStack; - - protected: - - struct TransformStruct - { - typedef std::set ObjectSet; - - TransformStruct():_canBeApplied(true) {} - - void add(osg::Object* obj) { _objectSet.insert(obj); } - - bool _canBeApplied; - ObjectSet _objectSet; - }; - - struct ObjectStruct - { - typedef std::set TransformSet; - - ObjectStruct():_canBeApplied(true),_matrixSet(false),_moreThanOneMatrixRequired(false) {} - - void add(TransformStack& transforms,osg::Matrix& matrix) - { - _transformSet.insert(transforms.begin(),transforms.end()); - if (!_matrixSet) - { - _matrixSet = true; - _moreThanOneMatrixRequired = false; - _matrix = matrix; - } - else if (_matrix!=matrix) - { - _moreThanOneMatrixRequired = true; - } - - } - - bool _canBeApplied; - bool _matrixSet; - bool _moreThanOneMatrixRequired; - osg::Matrix _matrix; - TransformSet _transformSet; - - }; - - typedef std::map TransformMap; - typedef std::map ObjectMap; - - void disableObject(osg::Object* object) - { - disableObject(_objectMap.find(object)); - } - - void disableObject(ObjectMap::iterator itr); - void disableTransform(osg::Transform* transform); - void doTransform(osg::Object* obj,osg::Matrix& matrix); - - bool _ignoreDynamicTransforms; - MatrixStack _matrixStack; - TransformStack _transformStack; - - TransformMap _transformMap; - ObjectMap _objectMap; - - - }; - - /** Remove the lowest static transforms in the scene.*/ - class OSGUTIL_EXPORT RemoveLowestStaticTransformsVisitor : public osg::NodeVisitor - { - public: - - - - RemoveLowestStaticTransformsVisitor(bool ignoreDynamicTransforms=true): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _ignoreDynamicTransforms(ignoreDynamicTransforms) {} - - virtual void apply(osg::Geode& geode); - virtual void apply(osg::Billboard& billboard); - virtual void apply(osg::LOD& lod); + virtual void apply(osg::Billboard& geode); virtual void apply(osg::Transform& transform); bool removeTransforms(); - typedef std::vector TransformStack; - typedef std::vector MatrixStack; - protected: - struct TransformStruct - { - typedef std::set ObjectSet; - - TransformStruct():_containsTransform(false),_canBeApplied(true) {} - - void add(osg::Object* obj) { _objectSet.insert(obj); } - - bool _containsTransform; - bool _canBeApplied; - ObjectSet _objectSet; - }; + typedef std::vector TransformStack; + typedef std::set DrawableSet; + typedef std::set BillboardSet; + typedef std::set TransformSet; - struct ObjectStruct - { - typedef std::set TransformSet; - - ObjectStruct():_canBeApplied(true),_matrixSet(false),_moreThanOneMatrixRequired(false) {} - - void add(osg::Transform* transform,osg::Matrix& matrix) - { - _transformSet.insert(transform); - if (!_matrixSet) - { - _matrixSet = true; - _moreThanOneMatrixRequired = false; - _matrix = matrix; - } - else if (_matrix!=matrix) - { - _moreThanOneMatrixRequired = true; - } - - } - - bool _canBeApplied; - bool _matrixSet; - bool _moreThanOneMatrixRequired; - osg::Matrix _matrix; - TransformSet _transformSet; - - }; - - typedef std::map TransformMap; - typedef std::map ObjectMap; - - void disableObject(osg::Object* object) - { - disableObject(_objectMap.find(object)); - } - - void disableObject(ObjectMap::iterator itr); - void disableTransform(osg::Transform* transform); - void doTransform(osg::Object* obj,osg::Matrix& matrix); - - bool _ignoreDynamicTransforms; - MatrixStack _matrixStack; TransformStack _transformStack; - - TransformMap _transformMap; - ObjectMap _objectMap; + DrawableSet _drawableSet; + BillboardSet _billboardSet; + TransformSet _transformSet; + }; + /** Remove rendundent nodes, such as groups with one single child.*/ class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public osg::NodeVisitor { diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 8ef8ef64f..1b4a6cf4b 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -21,7 +21,7 @@ using namespace osgUtil; void Optimizer::optimize(osg::Node* node, unsigned int options) { - + if (options & COMBINE_ADJACENT_LODS) { CombineLODsVisitor clv; @@ -31,25 +31,18 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) if (options & FLATTEN_STATIC_TRANSFORMS) { -// 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 -// { -// std::cout << "************ RemoveLowestStaticTransformsVisitor "<accept(fstv); -// result = fstv.removeTransforms(); -// ++i; -// } while (result); - - - + int i=0; + bool result = false; + do + { + osg::notify(osg::DEBUG_INFO) << "** RemoveStaticTransformsVisitor *** Pass "<accept(fstv); + result = fstv.removeTransforms(); + ++i; + } while (result); + } if (options & REMOVE_REDUNDENT_NODES) @@ -377,75 +370,172 @@ void Optimizer::StateVisitor::optimize() // Flatten static transforms //////////////////////////////////////////////////////////////////////////// -void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Geode& geode) +class CollectLowestTransformsVisitor : public osg::NodeVisitor { + public: - osg::Matrix matrix; - if (!_matrixStack.empty()) matrix = _matrixStack.back(); - for(unsigned int i=0;i matrix; - if (_matrixStack.empty()) + virtual void apply(osg::Node& node) { - matrix = osgNew osg::Matrix; - } - else - { - matrix = osgNew osg::Matrix(_matrixStack.back()); + if (node.getNumParents()) + { + traverse(node); + } + else + { + // for all current objects mark a NULL transform for them. + registerWithCurrentObjects(0); + } } - transform.getLocalToWorldMatrix(*matrix,this); + virtual void apply(osg::LOD& lod) + { + _currentObjectList.push_back(&lod); - _matrixStack.push_back(*matrix); + traverse(lod); - _transformStack.push_back(&transform); + _currentObjectList.pop_back(); + } - // simple traverse the children as if this Transform didn't exist. - traverse(transform); - - _transformStack.pop_back(); + virtual void apply(osg::Transform& transform) + { + // for all current objects associated this transform with them. + registerWithCurrentObjects(&transform); + } + + virtual void apply(osg::Geode& geode) + { + traverse(geode); + } + + virtual void apply(osg::Billboard& geode) + { + traverse(geode); + } - _matrixStack.pop_back(); - } -} -void Optimizer::FlattenStaticTransformsVisitor::doTransform(osg::Object* obj,osg::Matrix& matrix) + void collectDataFor(osg::Billboard* billboard) + { + _currentObjectList.push_back(billboard); + + billboard->accept(*this); + + _currentObjectList.pop_back(); + } + + void collectDataFor(osg::Drawable* drawable) + { + _currentObjectList.push_back(drawable); + + const osg::Drawable::ParentList& parents = drawable->getParents(); + for(osg::Drawable::ParentList::const_iterator itr=parents.begin(); + itr!=parents.end(); + ++itr) + { + (*itr)->accept(*this); + } + + _currentObjectList.pop_back(); + } + + void setUpMaps(); + void disableTransform(osg::Transform* transform); + bool removeTransforms(); + + protected: + + struct TransformStruct + { + typedef std::set ObjectSet; + + TransformStruct():_canBeApplied(true) {} + + void add(osg::Object* obj) + { + _objectSet.insert(obj); + } + + bool _canBeApplied; + ObjectSet _objectSet; + }; + + struct ObjectStruct + { + typedef std::set TransformSet; + + ObjectStruct():_canBeApplied(true),_moreThanOneMatrixRequired(false) {} + + void add(osg::Transform* transform) + { + if (transform) + { + if (transform->getDataVariance()==osg::Transform::DYNAMIC) _moreThanOneMatrixRequired=true; + else if (transform->getReferenceFrame()==osg::Transform::RELATIVE_TO_ABSOLUTE) _moreThanOneMatrixRequired=true; + else + { + if (_transformSet.empty()) transform->getLocalToWorldMatrix(_firstMatrix,0); + else + { + osg::Matrix matrix; + transform->getLocalToWorldMatrix(_firstMatrix,0); + if (_firstMatrix!=matrix) _moreThanOneMatrixRequired=true; + } + } + } + else + { + if (!_transformSet.empty()) + { + if (_firstMatrix!=osg::Matrix::identity()) _moreThanOneMatrixRequired=true; + } + + } + _transformSet.insert(transform); + } + + bool _canBeApplied; + bool _moreThanOneMatrixRequired; + osg::Matrix _firstMatrix; + TransformSet _transformSet; + + }; + + + void registerWithCurrentObjects(osg::Transform* transform) + { + for(ObjectList::iterator itr=_currentObjectList.begin(); + itr!=_currentObjectList.end(); + ++itr) + { + _objectMap[*itr].add(transform); + } + } + + typedef std::map TransformMap; + typedef std::map ObjectMap; + typedef std::vector ObjectList; + + void disableObject(osg::Object* object) + { + disableObject(_objectMap.find(object)); + } + + void disableObject(ObjectMap::iterator itr); + void doTransform(osg::Object* obj,osg::Matrix& matrix); + + + TransformMap _transformMap; + ObjectMap _objectMap; + ObjectList _currentObjectList; + +}; + + +void CollectLowestTransformsVisitor::doTransform(osg::Object* obj,osg::Matrix& matrix) { osg::Drawable* drawable = dynamic_cast(obj); if (drawable) @@ -503,12 +593,10 @@ void Optimizer::FlattenStaticTransformsVisitor::doTransform(osg::Object* obj,osg } } -void Optimizer::FlattenStaticTransformsVisitor::disableObject(ObjectMap::iterator itr) +void CollectLowestTransformsVisitor::disableObject(ObjectMap::iterator itr) { if (itr==_objectMap.end()) { - // Euston we have a problem.. - osg::notify(osg::WARN)<<"Warning: internal error Optimizer::FlattenStaticTransformsVisitor::disableObject()"<second; if (os._canBeApplied) { - doTransform(object,os._matrix); + doTransform(object,os._firstMatrix); } } + bool transformRemoved = false; + // clean up the transforms. for(TransformMap::iterator titr=_transformMap.begin(); titr!=_transformMap.end(); @@ -613,6 +705,8 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms() { if (titr->second._canBeApplied) { + transformRemoved = true; + osg::ref_ptr transform = titr->first; osg::ref_ptr group = osgNew osg::Group; group->setDataVariance(osg::Object::STATIC); @@ -632,287 +726,77 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms() } _objectMap.clear(); _transformMap.clear(); - _transformStack.clear(); - _matrixStack.clear(); + + return transformRemoved; } -//////////////////////////////////////////////////////////////////////////// -// Flatten static transforms -//////////////////////////////////////////////////////////////////////////// - -void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Geode& geode) +void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Geode& geode) { - osg::Transform* transform = NULL; - if (!_transformStack.back()) transform = _transformStack.back(); - osg::Matrix matrix; - if (!_matrixStack.empty()) matrix = _matrixStack.back(); - - for(unsigned int i=0;i(obj); - if (drawable) - { - TransformFunctor tf(matrix); - drawable->accept(tf); - drawable->dirtyBound(); - return; - } - - osg::LOD* lod = dynamic_cast(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;igetNumRanges();++i) - { - lod->setRange(i,lod->getRange(i)*ratio); - } - - lod->dirtyBound(); - return; - } - - osg::Billboard* billboard = dynamic_cast(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(unsigned int i=0;igetNumDrawables();++i) - { - billboard->setPos(i,billboard->getPos(i)*matrix); - billboard->getDrawable(i)->accept(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()"<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()"<second._canBeApplied) - { + cltv.setUpMaps(); - // 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); - } - } - - TransformMap::iterator titr; - for(titr=_transformMap.begin(); - titr!=_transformMap.end(); + for(TransformSet::iterator titr=_transformSet.begin(); + titr!=_transformSet.end(); ++titr) { - TransformStruct& ts = titr->second; - if (ts._containsTransform) - { - disableTransform(titr->first); - } + cltv.disableTransform(*titr); } - - // 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(titr=_transformMap.begin(); - titr!=_transformMap.end(); - ++titr) - { - if (titr->second._canBeApplied && titr->first) - { - osg::ref_ptr transform = titr->first; - osg::ref_ptr group = osgNew osg::Group; - group->setDataVariance(osg::Object::STATIC); - for(unsigned int i=0;igetNumChildren();++i) - { - for(unsigned int j=0;jgetNumParents();++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; + + return cltv.removeTransforms(); }