diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index 1f67f1673..6ec599577 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -44,12 +44,14 @@ class OSGUTIL_EXPORT Optimizer SHARE_DUPLICATE_STATE = 0x8, MERGE_GEOMETRY = 0x10, CHECK_GEOMETRY = 0x20, + SPATIALIZE_GROUPS = 0x40, ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | - CHECK_GEOMETRY + CHECK_GEOMETRY | + SPATIALIZE_GROUPS }; /** traverse the node and its subgraph with a series of optimization @@ -213,6 +215,24 @@ class OSGUTIL_EXPORT Optimizer static bool mergePrimitive(osg::DrawElementsUInt& lhs,osg::DrawElementsUInt& rhs); }; + + /** Spatialize scene into a balanced quad/oct tree.*/ + class OSGUTIL_EXPORT SpatializeGroupsVisitor : public osg::NodeVisitor + { + public: + + SpatializeGroupsVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Group& group); + + bool divide(unsigned int maxNumTreesPerCell=8); + + bool divide(osg::Group* group, unsigned int maxNumTreesPerCell); + + typedef std::set GroupsToDivideList; + GroupsToDivideList _groupsToDivideList; + + }; }; } diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index b6d3850ca..c27477858 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -110,7 +110,13 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) node->accept(mgv); } - + if (options & SPATIALIZE_GROUPS) + { + SpatializeGroupsVisitor sv; + node->accept(sv); + sv.divide(); + + } } @@ -1525,3 +1531,190 @@ bool Optimizer::MergeGeometryVisitor::mergePrimitive(osg::DrawElementsUInt& lhs, lhs.insert(lhs.end(),rhs.begin(),rhs.end()); return true; } + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Spatialize the scene to accelerate culling +// + +void Optimizer::SpatializeGroupsVisitor::apply(osg::Group& group) +{ + if (typeid(group)==typeid(osg::Group) || group.asTransform()) + { + _groupsToDivideList.insert(&group); + } + traverse(group); +} + +bool Optimizer::SpatializeGroupsVisitor::divide(unsigned int maxNumTreesPerCell) +{ + bool divided = false; + for(GroupsToDivideList::iterator itr=_groupsToDivideList.begin(); + itr!=_groupsToDivideList.end(); + ++itr) + { + if (divide(*itr,maxNumTreesPerCell)) divided = true; + } + return divided; +} + +bool Optimizer::SpatializeGroupsVisitor::divide(osg::Group* group, unsigned int maxNumTreesPerCell) +{ + if (group->getNumChildren()<=maxNumTreesPerCell) return false; + + // create the original box. + osg::BoundingBox bb; + unsigned int i; + for(i=0;igetNumChildren();++i) + { + bb.expandBy(group->getChild(i)->getBound().center()); + } + + float radius = bb.radius(); + float divide_distance = radius*0.7f; + bool xAxis = (bb.xMax()-bb.xMin())>divide_distance; + bool yAxis = (bb.yMax()-bb.yMin())>divide_distance; + bool zAxis = (bb.zMax()-bb.zMin())>divide_distance; + + std::cout<<"Dividing "<className()<<" num children = "<getNumChildren()<<" xAxis="<