diff --git a/examples/osgtext3D/osgtext3D.cpp b/examples/osgtext3D/osgtext3D.cpp index 1c1267b94..3046a2636 100644 --- a/examples/osgtext3D/osgtext3D.cpp +++ b/examples/osgtext3D/osgtext3D.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,6 @@ extern int main_orig(int, char**); extern int main_test(int, char**); - class Boundary { public: @@ -40,11 +40,15 @@ public: typedef std::pair Segment; typedef std::vector Segments; osg::ref_ptr _vertices; + unsigned int _start; + unsigned int _count; Segments _segments; Boundary(osg::Vec3Array* vertices, unsigned int start, unsigned int count) { _vertices = vertices; + _start = start; + _count = count; if ((*_vertices)[start]==(*_vertices)[start+count-1]) { @@ -56,21 +60,22 @@ public: } _segments.reserve(count-1); - for(unsigned int i=start; ireserve(new_vertices->size()+_segments.size()+1); + new_vertices->reserve(new_vertices->size() + _segments.size()+1 + _count); // create vertices unsigned int previous_second = _segments[0].second; osg::Vec3 newPoint = computeBisectorPoint(0, targetThickness); + unsigned int first = new_vertices->size(); new_vertices->push_back(newPoint); - ++count; + + if (_segments[0].first != _start) + { + //OSG_NOTICE<<"We have pruned from the start"<push_back(first); + } + } + else + { + face->push_back(first); + } + for(unsigned int i=1; i<_segments.size(); ++i) { - previous_second = _segments[i].second; newPoint = computeBisectorPoint(i, targetThickness); + unsigned int vi = new_vertices->size(); new_vertices->push_back(newPoint); - ++count; + + if (previous_second != _segments[i].first) + { + //OSG_NOTICE<<"Gap in boundary"<push_back(vi); + } + } + else + { + face->push_back(vi); + } + + previous_second = _segments[i].second; } - // repeat the first point to make it a full closed loop - new_vertices->push_back((*new_vertices)[first]); - ++count; + // fill the end of the polygon with repititions of the first index in the polygon to ensure + // that the orignal and new boundary polygons have the same number and pairing of indices. + // This ensures that the bevel can be created coherently. + while(face->size() < _count) + { + face->push_back(first); + } - // add DrawArrays primitive set for polygon - if (count!=0) geometry->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON, first, count)); + // add face primitive set for polygon + geometry->addPrimitiveSet(face); + + osg::DrawElementsUShort* bevel = new osg::DrawElementsUShort(GL_QUAD_STRIP); + bevel->setName("bevel"); + bevel->reserve(_count*2); + for(unsigned int i=0; i<_count; ++i) + { + unsigned int vi = new_vertices->size(); + new_vertices->push_back((*_vertices)[_start+i]); + bevel->push_back(vi); + bevel->push_back((*face)[i]); + } + geometry->addPrimitiveSet(bevel); } }; +osg::Geometry* getGeometryComponent(osg::Geometry* geometry, bool bevel) +{ + osg::Vec3Array* vertices = dynamic_cast(geometry->getVertexArray()); + if (!vertices) return 0; + + osg::Geometry* new_geometry = new osg::Geometry; + osg::Vec3Array* new_vertices = new osg::Vec3Array(*vertices); + new_geometry->setVertexArray(new_vertices); + + for(unsigned int i=0; igetNumPrimitiveSets(); ++i) + { + osg::PrimitiveSet* primitiveSet = geometry->getPrimitiveSet(i); + if (primitiveSet->getName()=="bevel") + { + if (bevel) new_geometry->addPrimitiveSet(primitiveSet); + } + else + { + if (!bevel) new_geometry->addPrimitiveSet(primitiveSet); + } + } + + osg::Vec4Array* new_colours = new osg::Vec4Array; + new_colours->push_back(bevel ? osg::Vec4(1.0,1.0,0.0,1.0) : osg::Vec4(1.0,0.0,0.0,1.0)); + new_geometry->setColorArray(new_colours); + new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + + if (!bevel) + { + osg::Vec3Array* normals = new osg::Vec3Array; + normals->push_back(osg::Vec3(0.0,0.0,1.0)); + new_geometry->setNormalArray(normals); + new_geometry->setNormalBinding(osg::Geometry::BIND_OVERALL); + } + + return new_geometry; +} + osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) { @@ -255,11 +344,6 @@ osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) osg::Geometry* new_geometry = new osg::Geometry; - osg::Vec4Array* new_colours = new osg::Vec4Array; - new_colours->push_back(osg::Vec4(1.0,1.0,0.0,1.0)); - new_geometry->setColorArray(new_colours); - new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL); - for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin(); itr != orig_primitives.end(); ++itr) @@ -268,8 +352,6 @@ osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness) if (drawArray && drawArray->getMode()==GL_POLYGON) { Boundary boundary(orig_vertices, drawArray->getFirst(), drawArray->getCount()); - boundary.computeAllThickness(); - boundary.removeAllSegmentsBelowThickness(thickness); boundary.addBoundaryToGeometry(new_geometry, thickness); } @@ -343,10 +425,20 @@ int main(int argc, char** argv) geometry->setColorArray(colours); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); - osg::Geometry* bevel = computeThickness(geometry, thickness); + osg::ref_ptr face_and_bevel = computeThickness(geometry, thickness); - if (bevel) geode->addDrawable(bevel); + osg::Geometry* bevel = getGeometryComponent(face_and_bevel, true); + if (bevel) + { + geode->addDrawable(bevel); + osgUtil::SmoothingVisitor smoother; + smoother.smooth(*bevel); + } + osg::Geometry* face = getGeometryComponent(face_and_bevel, false); + if (face) geode->addDrawable(face); + + if (useTessellator) { if (geometry) @@ -357,12 +449,12 @@ int main(int argc, char** argv) ts.retessellatePolygons(*geometry); } - if (bevel) + if (face) { osgUtil::Tessellator ts; ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); - ts.retessellatePolygons(*bevel); + ts.retessellatePolygons(*face); } } @@ -374,6 +466,8 @@ int main(int argc, char** argv) group->addChild(transform.get()); } + + std::string filename; if (arguments.read("-o", filename)) osgDB::writeNodeFile(*group, filename); @@ -381,4 +475,4 @@ int main(int argc, char** argv) viewer.setSceneData(group.get()); viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); return viewer.run(); -} \ No newline at end of file +}