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.
|
||||
*/
|
||||
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;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.*/
|
||||
void simplify(osg::Geometry& geometry, float sampleRatio);
|
||||
@@ -38,8 +50,11 @@ class OSGUTIL_EXPORT Simplifier
|
||||
|
||||
protected:
|
||||
|
||||
float _sampleRatio;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <osgUtil/TransformAttributeFunctor>
|
||||
#include <osgUtil/TriStripVisitor>
|
||||
#include <osgUtil/Tesselator>
|
||||
#include <osgUtil/Simplifier>
|
||||
|
||||
#include <typeinfo>
|
||||
#include <algorithm>
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
#include <osgUtil/Simplifier>
|
||||
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
#include <osgUtil/TriStripVisitor>
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
@@ -22,6 +25,15 @@
|
||||
using namespace osgUtil;
|
||||
|
||||
|
||||
struct dereference_less
|
||||
{
|
||||
template<class T>
|
||||
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<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
|
||||
{
|
||||
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<Point> _p1;
|
||||
osg::ref_ptr<Point> _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()<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;
|
||||
};
|
||||
|
||||
@@ -76,6 +130,17 @@ public:
|
||||
{
|
||||
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> _p2;
|
||||
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)
|
||||
{
|
||||
std::cout<<"addTriangle("<<p1<<","<<p2<<","<<p3<<")"<<std::endl;
|
||||
abort();
|
||||
#if 0
|
||||
//std::cout<<"addTriangle("<<p1<<","<<p2<<","<<p3<<")"<<std::endl;
|
||||
|
||||
// detect if triangle is degenerate.
|
||||
if (p1==p2 || p2==p3 || p1==p3) return 0;
|
||||
|
||||
@@ -148,31 +177,85 @@ public:
|
||||
triangle->_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("<<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:
|
||||
|
||||
typedef std::vector< osg::ref_ptr<osg::Array> > ArrayList;
|
||||
|
||||
osg::Geometry* _geometry;
|
||||
osg::ref_ptr<osg::Vec3Array> _vertexList;
|
||||
ArrayList _arrayList;
|
||||
|
||||
unsigned int _targetNumTriangles;
|
||||
EdgeSet _edgeSet;
|
||||
TriangleList _triangleList;
|
||||
@@ -202,6 +285,7 @@ typedef osg::TriangleIndexFunctor<CollectTriangleOperator> CollectTriangleIndexF
|
||||
void EdgeCollapse::setGeometry(osg::Geometry* geometry)
|
||||
{
|
||||
_geometry = geometry;
|
||||
_vertexList = dynamic_cast<osg::Vec3Array*>(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<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