From c80de01fd71a6b038712f796f2157e496cfab2d3 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 12 Apr 2004 21:29:31 +0000 Subject: [PATCH] Further work on the new osgUtil::Simplifier. --- include/osgUtil/Simplifier | 19 ++- src/osgUtil/Optimizer.cpp | 7 +- src/osgUtil/Simplifier.cpp | 234 ++++++++++++++++++++++++++++--------- 3 files changed, 204 insertions(+), 56 deletions(-) diff --git a/include/osgUtil/Simplifier b/include/osgUtil/Simplifier index 63b906564..aa2dee979 100644 --- a/include/osgUtil/Simplifier +++ b/include/osgUtil/Simplifier @@ -24,11 +24,23 @@ namespace osgUtil { /** A simplifier for reducing the number of traingles in osg::Geometry. */ -class OSGUTIL_EXPORT Simplifier +class OSGUTIL_EXPORT Simplifier : public osg::NodeVisitor { public: - Simplifier(); + Simplifier(float sampleRatio=0.5f); + + virtual void apply(osg::Geode& geode) + { + for(unsigned int i=0;iasGeometry(); + if (geometry) + { + simplify(*geometry,_sampleRatio); + } + } + } /** simply the geometry to defined ratio of original size.*/ void simplify(osg::Geometry& geometry, float sampleRatio); @@ -38,8 +50,11 @@ class OSGUTIL_EXPORT Simplifier protected: + float _sampleRatio; + }; + } #endif diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 0065b7524..ae18bf74b 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -215,7 +216,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) node->accept(tsv); tsv.stripify(); } - +#if 0 + // simplify geometry + osgUtil::Simplifier simplifier; + node->accept(simplifier); +#endif } diff --git a/src/osgUtil/Simplifier.cpp b/src/osgUtil/Simplifier.cpp index 2d4bb48ae..9dd32c3ad 100644 --- a/src/osgUtil/Simplifier.cpp +++ b/src/osgUtil/Simplifier.cpp @@ -15,6 +15,9 @@ #include +#include +#include + #include #include #include @@ -22,6 +25,15 @@ using namespace osgUtil; +struct dereference_less +{ + template + inline bool operator() (const T& lhs,const T& rhs) const + { + return *lhs < *rhs; + } +}; + class EdgeCollapse { public: @@ -39,26 +51,41 @@ public: bool collapseMinimumErrorEdge() { return false; } - void copyBackToGeometry() {} + void copyBackToGeometry(); struct Triangle; struct Edge; + struct Point; - typedef std::vector FloatList; + typedef std::vector FloatList; + typedef std::set,dereference_less> EdgeSet; + typedef std::set< osg::ref_ptr,dereference_less> PointSet; + typedef std::list< osg::ref_ptr > TriangleList; struct Point : public osg::Referenced { - Point() {} + Point():_index(0) {} unsigned int _index; - osg::Vec3 _vertex; - FloatList _attributes; + osg::Vec3 _vertex; + FloatList _attributes; + TriangleList _triangles; + + bool operator < ( const Point& rhs) const + { + if (_vertex < rhs._vertex) return true; + if (rhs._vertex < _vertex) return false; + + return _attributes < rhs._attributes; + } + + }; struct Edge : public osg::Referenced { - Edge() {} + Edge():_errorMetric(0.0f) {} osg::ref_ptr _p1; osg::ref_ptr _p2; @@ -69,6 +96,33 @@ public: void setErrorMetric(float errorMetric) { _errorMetric = errorMetric; } float getErrorMetric() const { return _errorMetric; } + bool operator < ( const Edge& rhs) const + { + if (getErrorMetric()getErrorMetric()) return false; + + if (_p1 < rhs._p1) return true; + if (rhs._p1 < _p1) return false; + + return (_p2 < rhs._p2); + } + + void addTriangle(Triangle* triangle) + { + if (!_t1) + { + _t1 = triangle; + } + else if (!_t2) + { + _t2 = triangle; + } + else + { + osg::notify(osg::NOTICE)<<"Warning too many traingles sharing edge"< _p1; osg::ref_ptr _p2; osg::ref_ptr _p3; @@ -87,47 +152,11 @@ public: - - struct LessErrorMetricFunctor - { - inline bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const - { - return lhs->getErrorMetric()getErrorMetric(); - } - }; - - struct LessTriangleFunctor - { - inline bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const - { - if (lhs->_p1 < rhs->_p1) return true; - if (lhs->_p1 > rhs->_p1) return false; - - if (lhs->_p2 < rhs->_p2) return true; - if (lhs->_p2 > rhs->_p2) return false; - - if (lhs->_p1 < rhs->_p3) return true; - return false; - } - }; - - struct LessPointFunctor - { - inline bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const - { - return lhs->_index_index; - } - }; - - typedef std::set,LessErrorMetricFunctor> EdgeSet; - typedef std::set< osg::ref_ptr, LessPointFunctor> PointSet; - typedef std::list< osg::ref_ptr > TriangleList; Triangle* addTriangle(unsigned int p1, unsigned int p2, unsigned int p3) { - std::cout<<"addTriangle("<_p2 = points[(lowest+1)%3]; triangle->_p3 = points[(lowest+2)%3]; - triangle->_e1 = addEdge(triangle, triangle->_p1, triangle->_p2); - triangle->_e2 = addEdge(triangle, triangle->_p2, triangle->_p3); - triangle->_e3 = addEdge(triangle, triangle->_p3, triangle->_p1); + triangle->_e1 = addEdge(triangle, triangle->_p1.get(), triangle->_p2.get()); + triangle->_e2 = addEdge(triangle, triangle->_p2.get(), triangle->_p3.get()); + triangle->_e3 = addEdge(triangle, triangle->_p3.get(), triangle->_p1.get()); - _triangleList.insert(triangle); + _triangleList.push_back(triangle); return triangle; -#endif + } Edge* addEdge(Triangle* triangle, Point* p1, Point* p2) { - std::cout<<"addEdge("< edge = new Edge; + if (p1_p1 = p1; + edge->_p2 = p2; + } + else + { + edge->_p1 = p2; + edge->_p2 = p1; + } + EdgeSet::iterator itr = _edgeSet.find(edge); + if (itr==_edgeSet.end()) + { + //std::cout<<" addEdge("<addTriangle(triangle); + + return 0; } - Point* addPoint(Triangle* triangle, Point* p1) + Point* addPoint(Triangle* triangle, unsigned int p1) { - std::cout<<"addPoint("< point = new Point; + point->_index = p1; + + if (_vertexList.valid() && p1<_vertexList->size()) + { + point->_vertex = (*_vertexList)[p1]; + } + + + PointSet::iterator itr = _pointSet.find(point); + if (itr==_pointSet.end()) + { + //std::cout<<" addPoint("<_triangles.push_back(triangle); + + return point.get(); } protected: + typedef std::vector< osg::ref_ptr > ArrayList; + osg::Geometry* _geometry; + osg::ref_ptr _vertexList; + ArrayList _arrayList; + unsigned int _targetNumTriangles; EdgeSet _edgeSet; TriangleList _triangleList; @@ -202,6 +285,7 @@ typedef osg::TriangleIndexFunctor CollectTriangleIndexF void EdgeCollapse::setGeometry(osg::Geometry* geometry) { _geometry = geometry; + _vertexList = dynamic_cast(geometry->getVertexArray()); CollectTriangleIndexFunctor collectTriangles; collectTriangles.setEdgeCollapse(this); @@ -209,7 +293,51 @@ void EdgeCollapse::setGeometry(osg::Geometry* geometry) _geometry->accept(collectTriangles); } -Simplifier::Simplifier() +void EdgeCollapse::copyBackToGeometry() +{ + osg::Vec3Array* vertices = new osg::Vec3Array(_pointSet.size()); + + unsigned int pos = 0; + for(PointSet::iterator pitr=_pointSet.begin(); + pitr!=_pointSet.end(); + ++pitr) + { + Point* point = const_cast((*pitr).get()); + point->_index = pos; + (*vertices)[pos++] = point->_vertex; + } + + osg::DrawElementsUInt* primitives = new osg::DrawElementsUInt(GL_TRIANGLES,_triangleList.size()*3); + pos = 0; + for(TriangleList::iterator titr=_triangleList.begin(); + titr!=_triangleList.end(); + ++titr) + { + Triangle* triangle = (*titr).get(); + (*primitives)[pos++] = triangle->_p1->_index; + (*primitives)[pos++] = triangle->_p2->_index; + (*primitives)[pos++] = triangle->_p3->_index; + } + + _geometry->setNormalArray(0); + //_geometry->setColorArray(0); + _geometry->setTexCoordArray(0,0); + _geometry->getPrimitiveSetList().clear(); + + _geometry->setVertexArray(vertices); + _geometry->addPrimitiveSet(primitives); + + osgUtil::SmoothingVisitor::smooth(*_geometry); + + osgUtil::TriStripVisitor stripper; + stripper.stripify(*_geometry); + +} + + +Simplifier::Simplifier(float sampleRatio): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _sampleRatio(sampleRatio) { }