void osgToy::FacetingVisitor::facet( osg::Geometry& geom ) { // count #surfaces, exit if none osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator itr; unsigned int numSurfacePrimitives=0; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { switch((*itr)->getMode()) { case osg::PrimitiveSet::TRIANGLES: case osg::PrimitiveSet::TRIANGLE_STRIP: case osg::PrimitiveSet::TRIANGLE_FAN: case osg::PrimitiveSet::QUADS: case osg::PrimitiveSet::QUAD_STRIP: case osg::PrimitiveSet::POLYGON: ++numSurfacePrimitives; break; default: break; } } if (!numSurfacePrimitives) return; // exit if no vertices osg::Vec3Array *coords = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!coords || !coords->size()) return; // generate the normals osg::Vec3Array *normals = new osg::Vec3Array(coords->size()); osg::TriangleIndexFunctor<FacetingOperator> ftif; ftif.set( coords, normals ); geom.accept(ftif); geom.setNormalArray( normals ); geom.setNormalIndices( geom.getVertexIndices() ); geom.setNormalBinding(osg::Geometry::BIND_PER_VERTEX); geom.dirtyDisplayList(); }
void Tessellator::retessellatePolygons(osg::Geometry &geom) { #ifdef OSG_GLU_AVAILABLE // turn the contour list into primitives, a little like Tessellator does but more generally osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return; // we currently don't handle geometry which use indices... if (geom.getVertexIndices() || geom.getNormalIndices() || geom.getColorIndices() || geom.getSecondaryColorIndices() || geom.getFogCoordIndices()) return; // not even text coord indices don't handle geometry which use indices... for(unsigned int unit=0;unit<geom.getNumTexCoordArrays();++unit) { if (geom.getTexCoordIndices(unit)) return; } if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) _numberVerts=0; // 09.04.04 GWM reset Tessellator // the reset is needed by the flt loader which reuses a Tessellator for triangulating polygons. // as such it might be reset by other loaders/developers in future. _index=0; // reset the counter for indexed vertices _extraPrimitives = 0; if (!_numberVerts) { _numberVerts=geom.getVertexArray()->getNumElements(); // save the contours for complex (winding rule) tessellations _Contours=geom.getPrimitiveSetList(); } // now cut out vertex attributes added on any previous tessellation reduceArray(geom.getVertexArray(), _numberVerts); reduceArray(geom.getColorArray(), _numberVerts); reduceArray(geom.getNormalArray(), _numberVerts); reduceArray(geom.getFogCoordArray(), _numberVerts); for(unsigned int unit1=0;unit1<geom.getNumTexCoordArrays();++unit1) { reduceArray(geom.getTexCoordArray(unit1), _numberVerts); } // remove the existing primitives. unsigned int nprimsetoriginal= geom.getNumPrimitiveSets(); if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal); // the main difference from osgUtil::Tessellator for Geometry sets of multiple contours is that the begin/end tessellation // occurs around the whole set of contours. if (_ttype==TESS_TYPE_GEOMETRY) { beginTessellation(); gluTessProperty(_tobj, GLU_TESS_WINDING_RULE, _wtype); gluTessProperty(_tobj, GLU_TESS_BOUNDARY_ONLY , _boundaryOnly); } // process all the contours into the Tessellator int noContours = _Contours.size(); int currentPrimitive = 0; for(int primNo=0;primNo<noContours;++primNo) { osg::ref_ptr<osg::PrimitiveSet> primitive = _Contours[primNo].get(); if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) { // this recovers the 'old' tessellation which just retessellates single polygons. if (primitive->getMode()==osg::PrimitiveSet::POLYGON || _ttype==TESS_TYPE_DRAWABLE) { if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) { osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get()); unsigned int first = drawArrayLengths->getFirst(); for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin(); itr!=drawArrayLengths->end(); ++itr) { beginTessellation(); unsigned int last = first + *itr; addContour(primitive->getMode(),first,last,vertices); first = last; endTessellation(); collectTessellation(geom, currentPrimitive); currentPrimitive++; } } else { if (primitive->getNumIndices()>3) { // April 2005 gwm only retessellate "complex" polygons beginTessellation(); addContour(primitive.get(), vertices); endTessellation(); collectTessellation(geom, currentPrimitive); currentPrimitive++; } else { // April 2005 gwm triangles don't need to be retessellated geom.addPrimitiveSet(primitive.get()); } } } else { // copy the contour primitive as it is not being tessellated geom.addPrimitiveSet(primitive.get()); } } else { if (primitive->getMode()==osg::PrimitiveSet::POLYGON || primitive->getMode()==osg::PrimitiveSet::QUADS || primitive->getMode()==osg::PrimitiveSet::TRIANGLES || primitive->getMode()==osg::PrimitiveSet::LINE_LOOP || primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP || primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN || primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP) { addContour(primitive.get(), vertices); } else { // copy the contour primitive as it is not being tessellated // in this case points, lines or line_strip geom.addPrimitiveSet(primitive.get()); } } } if (_ttype==TESS_TYPE_GEOMETRY) { endTessellation(); collectTessellation(geom, 0); } #endif }