diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index bb191bfb9..22ddbabc5 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -48,13 +48,7 @@ class OSGUTIL_EXPORT Optimizer { public: - typedef std::vector MatrixStack; - typedef std::set TransformList; - - MatrixStack _matrixStack; - TransformList _transformList; - bool _ignoreDynamicTransforms; FlattenStaticTransformsVisitor(bool ignoreDynamicTransforms=true): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), @@ -67,6 +61,74 @@ class OSGUTIL_EXPORT Optimizer void removeTransforms(); + protected: + + + typedef std::vector TransformStack; + typedef std::vector MatrixStack; + + 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 rendundent nodes, such as groups with one single child.*/ diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 78970b7d8..877cd6590 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -24,14 +24,14 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) node->accept(clv); clv.combineLODs(); } -/* + if (options & FLATTEN_STATIC_TRANSFORMS) { FlattenStaticTransformsVisitor fstv; node->accept(fstv); fstv.removeTransforms(); } -*/ + if (options & REMOVE_REDUNDENT_NODES) { RemoveRedundentNodesVisitor rrnv; @@ -291,13 +291,11 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Geode& geode) { if (!_matrixStack.empty()) { - TransformFunctor tf(_matrixStack.back()); for(int i=0;iapplyAttributeOperation(tf); - geode.getDrawable(i)->dirtyBound(); + // register each drawable with the objectMap. + _objectMap[geode.getDrawable(i)].add(_transformStack,_matrixStack.back()); } - geode.dirtyBound(); } } @@ -305,23 +303,8 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Billboard& billboard) { if (!_matrixStack.empty()) { - osg::Matrix& matrix = _matrixStack.back(); - 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;iapplyAttributeOperation(tf); - } - - billboard.dirtyBound(); + // register ourselves with the objectMap. + _objectMap[&billboard].add(_transformStack,_matrixStack.back()); } } @@ -329,25 +312,10 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::LOD& lod) { if (!_matrixStack.empty()) { - osg::Matrix& matrix = _matrixStack.back(); - 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(int i=0;i(obj); + if (drawable) + { + TransformFunctor tf(matrix); + drawable->applyAttributeOperation(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(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(int i=0;igetNumDrawables();++i) + { + billboard->setPos(i,billboard->getPos(i)*matrix); + billboard->getDrawable(i)->applyAttributeOperation(tf); + } + + billboard->dirtyBound(); + + return; + } +} + +void Optimizer::FlattenStaticTransformsVisitor::disableObject(ObjectMap::iterator itr) +{ + if (itr==_transformMap.end()) + { + // Euston we have a problem.. + osg::notify(osg::WARN)<<"Warning: internal error Optimizer::FlattenStaticTransformsVisitor::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::FlattenStaticTransformsVisitor::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::FlattenStaticTransformsVisitor::disableTransform()"<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); + } + } +} + void Optimizer::FlattenStaticTransformsVisitor::removeTransforms() { - for(TransformList::iterator itr=_transformList.begin(); - itr!=_transformList.end(); - ++itr) - { - osg::ref_ptr transform = *itr; - osg::ref_ptr group = new osg::Group; - int i; - for(i=0;igetNumChildren();++i) + // 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) { - for(int j=0;jgetNumParents();++j) + _transformMap[*titr].add(object); + } + } + + + // 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) { - group->addChild(transform->getChild(i)); + disableObject(oitr); } } - - for(i=transform->getNumParents()-1;i>=0;--i) - { - transform->getParent(i)->replaceChild(transform.get(),group.get()); - } - } - _transformList.clear(); + + // 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); + } + } + + + // clean up the transforms. + for(TransformMap::iterator titr=_transformMap.begin(); + titr!=_transformMap.end(); + ++titr) + { + if (titr->second._canBeApplied) + { + + + osg::ref_ptr transform = titr->first; + osg::ref_ptr group = new osg::Group; + + int i; + for(i=0;igetNumChildren();++i) + { + for(int j=0;jgetNumParents();++j) + { + group->addChild(transform->getChild(i)); + } + } + + for(i=transform->getNumParents()-1;i>=0;--i) + { + transform->getParent(i)->replaceChild(transform.get(),group.get()); + } + } + } + _objectMap.clear(); + _transformMap.clear(); + _transformStack.clear(); + _matrixStack.clear(); } @@ -425,7 +559,6 @@ void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Group& group) traverse(group); } - void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes() { for(NodeList::iterator itr=_redundentNodeList.begin();