From 075b1b769ce6dffa9dcaaf5062f7bcb4f2bbc1b7 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 30 Jul 2010 19:39:38 +0000 Subject: [PATCH] Beginning of crease angle support for SmoothingVisitor to all it duplicate vertices are creases thus enabling separate normals for triangles adjacent to the creases. --- examples/osgtext3D/osgtext3D.cpp | 11 +- include/osgUtil/SmoothingVisitor | 11 +- src/osgUtil/SmoothingVisitor.cpp | 272 +++++++++++++++++++++++++++++-- 3 files changed, 276 insertions(+), 18 deletions(-) diff --git a/examples/osgtext3D/osgtext3D.cpp b/examples/osgtext3D/osgtext3D.cpp index 3046a2636..8fd8cd676 100644 --- a/examples/osgtext3D/osgtext3D.cpp +++ b/examples/osgtext3D/osgtext3D.cpp @@ -392,12 +392,18 @@ int main(int argc, char** argv) if (!font) return 1; OSG_NOTICE<<"Read font "<(geom.getVertexArray()); if (!coords || !coords->size()) return; - + osg::Vec3Array *normals = new osg::Vec3Array(coords->size()); osg::Vec3Array::iterator nitr; @@ -136,7 +133,7 @@ void SmoothingVisitor::smooth(osg::Geometry& geom) TriangleFunctor stf; stf.set(&(coords->front()),coords->size(),&(normals->front())); - + geom.accept(stf); for(nitr= normals->begin(); @@ -145,7 +142,6 @@ void SmoothingVisitor::smooth(osg::Geometry& geom) { nitr->normalize(); } - geom.setNormalArray( normals ); geom.setNormalIndices( geom.getVertexIndices() ); geom.setNormalBinding(osg::Geometry::BIND_PER_VERTEX); @@ -155,11 +151,257 @@ void SmoothingVisitor::smooth(osg::Geometry& geom) } +struct SmoothTriangleIndexFunctor +{ + SmoothTriangleIndexFunctor(): + _vertices(0), + _normals(0) + { + } + + bool set(osg::Vec3Array* vertices, osg::Vec3Array* normals) + { + _vertices = vertices; + _normals = normals; + + if (!_vertices) + { + OSG_NOTICE<<"Warning: SmoothTriangleIndexFunctor::set(..) requires a valid vertex arrays."<begin(); + itr != _normals->end(); + ++itr) + { + (*itr).set(0.0f,0.0f,0.0f); + } + + return true; + } + + void normalize() + { + if (!_normals) return; + + for(osg::Vec3Array::iterator itr = _normals->begin(); + itr != _normals->end(); + ++itr) + { + (*itr).normalize(); + } + } + + void operator() (unsigned int p1, unsigned int p2, unsigned int p3) + { + const osg::Vec3& v1 = (*_vertices)[p1]; + const osg::Vec3& v2 = (*_vertices)[p2]; + const osg::Vec3& v3 = (*_vertices)[p3]; + osg::Vec3 normal( (v2-v1)^(v3-v1) ); + + normal.normalize(); + + (*_normals)[p1] += normal; + (*_normals)[p2] += normal; + (*_normals)[p3] += normal; + } + + osg::Vec3Array* _vertices; + osg::Vec3Array* _normals; +}; + + + +struct FindSharpEdgesFunctor +{ + FindSharpEdgesFunctor(): + _vertices(0), + _normals(0), + _maxDeviationDotProduct(0.0f) + { + } + + bool set(osg::Vec3Array* vertices, osg::Vec3Array* normals, float maxDeviationDotProduct) + { + _vertices = vertices; + _normals = normals; + _maxDeviationDotProduct = maxDeviationDotProduct; + + if (!_vertices) + { + OSG_NOTICE<<"Warning: SmoothTriangleIndexFunctor::set(..) requires a valid vertex arrays."<get(); + OSG_NOTICE<<" pv._point = "<_point<<" triangles "<_triangles.size()< Triangles; + unsigned int _point; + Triangles _triangles; + }; + + typedef std::vector< osg::ref_ptr > ProblemVertexVector; + typedef std::list< osg::ref_ptr > ProblemVertexList; + + osg::Vec3Array* _vertices; + osg::Vec3Array* _normals; + float _maxDeviationDotProduct; + ProblemVertexVector _problemVertexVector; + ProblemVertexList _problemVertexList; +}; + + +static void smooth_new(osg::Geometry& geom, double creaseAngle) +{ + OSG_NOTICE<<"smooth_new("<<&geom<<", "<(geom.getVertexArray()); + if (!vertices) return; + + osg::Vec3Array* normals = dynamic_cast(geom.getNormalArray()); + if (!normals) + { + normals = new osg::Vec3Array(vertices->size()); + geom.setNormalArray(normals); + geom.setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + } + + osg::TriangleIndexFunctor stif; + if (stif.set(vertices, normals)) + { + // accumulate all the normals + geom.accept(stif); + + // normalize the normals + stif.normalize(); + } + + osg::TriangleIndexFunctor fsef; + if (fsef.set(vertices, normals, cos(creaseAngle*0.5))) + { + // look normals that deviate too far + geom.accept(fsef); + fsef.listProblemVertices(); + } +} + +} + + +SmoothingVisitor::SmoothingVisitor(): + _creaseAngle(osg::PI) +{ + setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN); +} + +SmoothingVisitor::~SmoothingVisitor() +{ +} + +void SmoothingVisitor::smooth(osg::Geometry& geom, double creaseAngle) +{ + if (creaseAngle==osg::PI) + { + Smoother::smooth_old(geom); + } + else + { + Smoother::smooth_new(geom, creaseAngle); + } +} + + void SmoothingVisitor::apply(osg::Geode& geode) { for(unsigned int i = 0; i < geode.getNumDrawables(); i++ ) { osg::Geometry* geom = dynamic_cast(geode.getDrawable(i)); - if (geom) smooth(*geom); + if (geom) smooth(*geom, _creaseAngle); } }