Further work on the new osgUtil::Simplifier.

This commit is contained in:
Robert Osfield
2004-04-12 21:29:31 +00:00
parent ceec7ae86d
commit c80de01fd7
3 changed files with 204 additions and 56 deletions

View File

@@ -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

View File

@@ -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
}

View File

@@ -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)
{
}