Further work on the new osgUtil::Simplifier.
This commit is contained in:
@@ -24,11 +24,23 @@ namespace osgUtil {
|
|||||||
|
|
||||||
/** A simplifier for reducing the number of traingles in osg::Geometry.
|
/** A simplifier for reducing the number of traingles in osg::Geometry.
|
||||||
*/
|
*/
|
||||||
class OSGUTIL_EXPORT Simplifier
|
class OSGUTIL_EXPORT Simplifier : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Simplifier();
|
Simplifier(float sampleRatio=0.5f);
|
||||||
|
|
||||||
|
virtual void apply(osg::Geode& geode)
|
||||||
|
{
|
||||||
|
for(unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||||
|
{
|
||||||
|
osg::Geometry* geometry = geode.getDrawable(i)->asGeometry();
|
||||||
|
if (geometry)
|
||||||
|
{
|
||||||
|
simplify(*geometry,_sampleRatio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** simply the geometry to defined ratio of original size.*/
|
/** simply the geometry to defined ratio of original size.*/
|
||||||
void simplify(osg::Geometry& geometry, float sampleRatio);
|
void simplify(osg::Geometry& geometry, float sampleRatio);
|
||||||
@@ -38,8 +50,11 @@ class OSGUTIL_EXPORT Simplifier
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
float _sampleRatio;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <osgUtil/TransformAttributeFunctor>
|
#include <osgUtil/TransformAttributeFunctor>
|
||||||
#include <osgUtil/TriStripVisitor>
|
#include <osgUtil/TriStripVisitor>
|
||||||
#include <osgUtil/Tesselator>
|
#include <osgUtil/Tesselator>
|
||||||
|
#include <osgUtil/Simplifier>
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -215,7 +216,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
|||||||
node->accept(tsv);
|
node->accept(tsv);
|
||||||
tsv.stripify();
|
tsv.stripify();
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
// simplify geometry
|
||||||
|
osgUtil::Simplifier simplifier;
|
||||||
|
node->accept(simplifier);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
#include <osgUtil/Simplifier>
|
#include <osgUtil/Simplifier>
|
||||||
|
|
||||||
|
#include <osgUtil/SmoothingVisitor>
|
||||||
|
#include <osgUtil/TriStripVisitor>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -22,6 +25,15 @@
|
|||||||
using namespace osgUtil;
|
using namespace osgUtil;
|
||||||
|
|
||||||
|
|
||||||
|
struct dereference_less
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
inline bool operator() (const T& lhs,const T& rhs) const
|
||||||
|
{
|
||||||
|
return *lhs < *rhs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class EdgeCollapse
|
class EdgeCollapse
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -39,26 +51,41 @@ public:
|
|||||||
|
|
||||||
bool collapseMinimumErrorEdge() { return false; }
|
bool collapseMinimumErrorEdge() { return false; }
|
||||||
|
|
||||||
void copyBackToGeometry() {}
|
void copyBackToGeometry();
|
||||||
|
|
||||||
struct Triangle;
|
struct Triangle;
|
||||||
struct Edge;
|
struct Edge;
|
||||||
|
struct Point;
|
||||||
|
|
||||||
typedef std::vector<float> FloatList;
|
typedef std::vector<float> FloatList;
|
||||||
|
typedef std::set<osg::ref_ptr<Edge>,dereference_less> EdgeSet;
|
||||||
|
typedef std::set< osg::ref_ptr<Point>,dereference_less> PointSet;
|
||||||
|
typedef std::list< osg::ref_ptr<Triangle> > TriangleList;
|
||||||
|
|
||||||
struct Point : public osg::Referenced
|
struct Point : public osg::Referenced
|
||||||
{
|
{
|
||||||
Point() {}
|
Point():_index(0) {}
|
||||||
|
|
||||||
unsigned int _index;
|
unsigned int _index;
|
||||||
|
|
||||||
osg::Vec3 _vertex;
|
osg::Vec3 _vertex;
|
||||||
FloatList _attributes;
|
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
|
struct Edge : public osg::Referenced
|
||||||
{
|
{
|
||||||
Edge() {}
|
Edge():_errorMetric(0.0f) {}
|
||||||
|
|
||||||
osg::ref_ptr<Point> _p1;
|
osg::ref_ptr<Point> _p1;
|
||||||
osg::ref_ptr<Point> _p2;
|
osg::ref_ptr<Point> _p2;
|
||||||
@@ -69,6 +96,33 @@ public:
|
|||||||
void setErrorMetric(float errorMetric) { _errorMetric = errorMetric; }
|
void setErrorMetric(float errorMetric) { _errorMetric = errorMetric; }
|
||||||
float getErrorMetric() const { return _errorMetric; }
|
float getErrorMetric() const { return _errorMetric; }
|
||||||
|
|
||||||
|
bool operator < ( const Edge& rhs) const
|
||||||
|
{
|
||||||
|
if (getErrorMetric()<rhs.getErrorMetric()) return true;
|
||||||
|
else if (rhs.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"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float _errorMetric;
|
float _errorMetric;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,6 +130,17 @@ public:
|
|||||||
{
|
{
|
||||||
Triangle() {}
|
Triangle() {}
|
||||||
|
|
||||||
|
inline bool operator < (const Triangle& rhs) const
|
||||||
|
{
|
||||||
|
if (_p1 < rhs._p1) return true;
|
||||||
|
if (rhs._p1 < _p1) return false;
|
||||||
|
|
||||||
|
if (_p2 < rhs._p2) return true;
|
||||||
|
if (rhs._p2 < _p2) return false;
|
||||||
|
|
||||||
|
return (_p3 < rhs._p3);
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<Point> _p1;
|
osg::ref_ptr<Point> _p1;
|
||||||
osg::ref_ptr<Point> _p2;
|
osg::ref_ptr<Point> _p2;
|
||||||
osg::ref_ptr<Point> _p3;
|
osg::ref_ptr<Point> _p3;
|
||||||
@@ -87,47 +152,11 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct LessErrorMetricFunctor
|
|
||||||
{
|
|
||||||
inline bool operator() (const osg::ref_ptr<Edge>& lhs,const osg::ref_ptr<Edge>& rhs) const
|
|
||||||
{
|
|
||||||
return lhs->getErrorMetric()<rhs->getErrorMetric();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LessTriangleFunctor
|
|
||||||
{
|
|
||||||
inline bool operator() (const osg::ref_ptr<Triangle>& lhs,const osg::ref_ptr<Triangle>& 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<Point>& lhs,const osg::ref_ptr<Point>& rhs) const
|
|
||||||
{
|
|
||||||
return lhs->_index<rhs->_index;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::set<osg::ref_ptr<Edge>,LessErrorMetricFunctor> EdgeSet;
|
|
||||||
typedef std::set< osg::ref_ptr<Point>, LessPointFunctor> PointSet;
|
|
||||||
typedef std::list< osg::ref_ptr<Triangle> > TriangleList;
|
|
||||||
|
|
||||||
Triangle* addTriangle(unsigned int p1, unsigned int p2, unsigned int p3)
|
Triangle* addTriangle(unsigned int p1, unsigned int p2, unsigned int p3)
|
||||||
{
|
{
|
||||||
std::cout<<"addTriangle("<<p1<<","<<p2<<","<<p3<<")"<<std::endl;
|
//std::cout<<"addTriangle("<<p1<<","<<p2<<","<<p3<<")"<<std::endl;
|
||||||
abort();
|
|
||||||
#if 0
|
|
||||||
// detect if triangle is degenerate.
|
// detect if triangle is degenerate.
|
||||||
if (p1==p2 || p2==p3 || p1==p3) return 0;
|
if (p1==p2 || p2==p3 || p1==p3) return 0;
|
||||||
|
|
||||||
@@ -148,31 +177,85 @@ public:
|
|||||||
triangle->_p2 = points[(lowest+1)%3];
|
triangle->_p2 = points[(lowest+1)%3];
|
||||||
triangle->_p3 = points[(lowest+2)%3];
|
triangle->_p3 = points[(lowest+2)%3];
|
||||||
|
|
||||||
triangle->_e1 = addEdge(triangle, triangle->_p1, triangle->_p2);
|
triangle->_e1 = addEdge(triangle, triangle->_p1.get(), triangle->_p2.get());
|
||||||
triangle->_e2 = addEdge(triangle, triangle->_p2, triangle->_p3);
|
triangle->_e2 = addEdge(triangle, triangle->_p2.get(), triangle->_p3.get());
|
||||||
triangle->_e3 = addEdge(triangle, triangle->_p3, triangle->_p1);
|
triangle->_e3 = addEdge(triangle, triangle->_p3.get(), triangle->_p1.get());
|
||||||
|
|
||||||
_triangleList.insert(triangle);
|
_triangleList.push_back(triangle);
|
||||||
|
|
||||||
return triangle;
|
return triangle;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Edge* addEdge(Triangle* triangle, Point* p1, Point* p2)
|
Edge* addEdge(Triangle* triangle, Point* p1, Point* p2)
|
||||||
{
|
{
|
||||||
std::cout<<"addEdge("<<p1<<","<<p2<<")"<<std::endl;
|
//std::cout<<"addEdge("<<p1<<","<<p2<<")"<<std::endl;
|
||||||
|
osg::ref_ptr<Edge> edge = new Edge;
|
||||||
|
if (p1<p2)
|
||||||
|
{
|
||||||
|
edge->_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("<<edge.get()<<")"<<std::endl;
|
||||||
|
_edgeSet.insert(edge);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edge = *itr;
|
||||||
|
//std::cout<<" reuseEdge("<<edge.get()<<")"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
edge->addTriangle(triangle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point* addPoint(Triangle* triangle, Point* p1)
|
Point* addPoint(Triangle* triangle, unsigned int p1)
|
||||||
{
|
{
|
||||||
std::cout<<"addPoint("<<p1<<")"<<std::endl;
|
|
||||||
|
osg::ref_ptr<Point> 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("<<point.get()<<")"<<std::endl;
|
||||||
|
_pointSet.insert(point);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
point = *itr;
|
||||||
|
//std::cout<<" reusePoint("<<point.get()<<")"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
point->_triangles.push_back(triangle);
|
||||||
|
|
||||||
|
return point.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
typedef std::vector< osg::ref_ptr<osg::Array> > ArrayList;
|
||||||
|
|
||||||
osg::Geometry* _geometry;
|
osg::Geometry* _geometry;
|
||||||
|
osg::ref_ptr<osg::Vec3Array> _vertexList;
|
||||||
|
ArrayList _arrayList;
|
||||||
|
|
||||||
unsigned int _targetNumTriangles;
|
unsigned int _targetNumTriangles;
|
||||||
EdgeSet _edgeSet;
|
EdgeSet _edgeSet;
|
||||||
TriangleList _triangleList;
|
TriangleList _triangleList;
|
||||||
@@ -202,6 +285,7 @@ typedef osg::TriangleIndexFunctor<CollectTriangleOperator> CollectTriangleIndexF
|
|||||||
void EdgeCollapse::setGeometry(osg::Geometry* geometry)
|
void EdgeCollapse::setGeometry(osg::Geometry* geometry)
|
||||||
{
|
{
|
||||||
_geometry = geometry;
|
_geometry = geometry;
|
||||||
|
_vertexList = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
|
||||||
|
|
||||||
CollectTriangleIndexFunctor collectTriangles;
|
CollectTriangleIndexFunctor collectTriangles;
|
||||||
collectTriangles.setEdgeCollapse(this);
|
collectTriangles.setEdgeCollapse(this);
|
||||||
@@ -209,7 +293,51 @@ void EdgeCollapse::setGeometry(osg::Geometry* geometry)
|
|||||||
_geometry->accept(collectTriangles);
|
_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<Point*>((*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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user