Changeset 3209

Show
Ignore:
Timestamp:
08/01/04 12:36:02 (10 years ago)
Author:
robert
Message:

From Geoff Michel, new osgtesselate example, and new features in osgUtil::Tesselator.

Location:
OpenSceneGraph/trunk
Files:
7 added
3 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/VisualStudio/VisualStudio.dsw

    r3207 r3209  
    15971597############################################################################### 
    15981598 
     1599Project: "Example osgtesselate"=.\examples\osgtesselate\osgtesselate.dsp - Package Owner=<4> 
     1600 
     1601Package=<5> 
     1602{{{ 
     1603}}} 
     1604 
     1605Package=<4> 
     1606{{{ 
     1607    Begin Project Dependency 
     1608    Project_Dep_Name Core osg 
     1609    End Project Dependency 
     1610    Begin Project Dependency 
     1611    Project_Dep_Name Core osgDB 
     1612    End Project Dependency 
     1613    Begin Project Dependency 
     1614    Project_Dep_Name Core osgGA 
     1615    End Project Dependency 
     1616    Begin Project Dependency 
     1617    Project_Dep_Name Core osgProducer 
     1618    End Project Dependency 
     1619    Begin Project Dependency 
     1620    Project_Dep_Name Core osgUtil 
     1621    End Project Dependency 
     1622    Begin Project Dependency 
     1623    Project_Dep_Name Core osgText 
     1624    End Project Dependency 
     1625}}} 
     1626 
     1627############################################################################### 
     1628 
    15991629Project: "Example osgtext"=.\examples\osgtext\osgtextdemo.dsp - Package Owner=<4> 
    16001630 
  • OpenSceneGraph/trunk/include/osgUtil/Tesselator

    r1529 r3209  
    3131namespace osgUtil { 
    3232 
    33 /** A simple class for tessellating a single polygon boundary. 
    34   * Currently uses old style glu tessellation functions for portability. 
    35   * It be nice to use the modern glu tessellation functions or to find 
    36   * a small set of code for doing this job better.*/ 
    37 class OSGUTIL_EXPORT Tesselator 
     33/** Originally a simple class for tessellating a single polygon boundary. 
     34  * Using old style glu tessellation functions for portability. 
     35  * Upgraded Jan 2004 to use the modern glu tessellation functions.*/ 
     36 
     37class OSGUTIL_EXPORT Tesselator : public osg::Referenced 
    3838{ 
    3939    public: 
     
    4242        ~Tesselator(); 
    4343 
    44         enum InputBoundaryDirection 
    45         { 
    46             CLOCK_WISE, 
    47             COUNTER_CLOCK_WISE 
    48         }; 
    49          
     44        /** The winding rule, see red book ch 11. */ 
     45        enum WindingType{ 
     46            TESS_WINDING_ODD          = GLU_TESS_WINDING_ODD, 
     47            TESS_WINDING_NONZERO      = GLU_TESS_WINDING_NONZERO     , 
     48            TESS_WINDING_POSITIVE     = GLU_TESS_WINDING_POSITIVE    , 
     49            TESS_WINDING_NEGATIVE     = GLU_TESS_WINDING_NEGATIVE    , 
     50            TESS_WINDING_ABS_GEQ_TWO  =    GLU_TESS_WINDING_ABS_GEQ_TWO 
     51        } ; 
     52 
     53        /** we interpret all contours in the geometry as a single set to be tesselated or 
     54         * each separate drawable's contours needs to be tesselated. */ 
     55        enum TesselationType { 
     56            TESS_TYPE_GEOMETRY, // tesselate everything in the geometry object 
     57            TESS_TYPE_DRAWABLE, // tesselate each polygon, triangles & quads drawables in geometry separately 
     58            TESS_TYPE_POLYGONS // tesselate ONLY polygon drawables in geometry separately 
     59        }; 
     60 
     61        /** Set and get tesselation request boundary only on/off */ 
     62        void setBoundaryOnly (const bool tt) { _boundaryOnly=tt;} 
     63        inline const bool getBoundaryOnly ( ) { return _boundaryOnly;} 
     64 
     65        /** Set and get tesselation windong rule */ 
     66        void setWindingType (const WindingType wt) { _wtype=wt;} 
     67        inline const WindingType getWindingType ( ) { return _wtype;} 
     68 
     69        /** Set and get tesselation type */ 
     70        void setTesselationType (const TesselationType tt) { _ttype=tt;} 
     71        inline const TesselationType getTesselationType ( ) { return _ttype;} 
     72 
     73        /** Change the contours lists of the geometry into tesselated primitives (the 
     74          * list of primitives in the original geometry is stored in the tesselator for 
     75          * possible re-use.  
     76          * The name remains retesselatePolygons although it now handles trifans, strips, quads etc. 
     77          * as well as Polygons so as to not break old codes relying on this function name. */ 
     78        void retesselatePolygons(osg::Geometry &cxgeom); 
     79 
     80        osg::Geometry::PrimitiveSetList  getContours() { return _Contours;} 
     81 
    5082        typedef std::vector<osg::Vec3*> VertexPointList; 
    5183         
     
    72104        PrimList& getPrimList() { return _primList; }         
    73105         
    74         void retesselatePolygons(osg::Geometry& geom); 
    75          
    76106        void reset(); 
    77107         
    78108    protected: 
    79          
     109 
     110        /** remove unused parts of the array, eg for wehn retesselating 
     111         * tesselation can introduce extra vertices for concave or crossing boundaries, 
     112         * these will leak memory if not removed when retesselating. */ 
     113        void reduceArray(osg::Array * cold, const unsigned int nnu); 
     114 
     115        void collectTesselation(osg::Geometry &cxgeom); 
     116         
     117        typedef std::map<osg::Vec3*,unsigned int> VertexPtrToIndexMap; 
     118        void addContour(osg::PrimitiveSet* primitive, osg::Vec3Array* vertices); 
     119        void handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap); 
     120 
    80121        void begin(GLenum mode); 
    81122        void vertex(osg::Vec3* vertex); 
     
    104145         
    105146            NewVertex(): 
     147                _vpos(0), 
    106148                _f1(0), 
    107149                _v1(0), 
     
    114156             
    115157            NewVertex(const NewVertex& nv): 
     158                _vpos(nv._vpos), 
    116159                _f1(nv._f1), 
    117160                _v1(nv._v1), 
     
    123166                _v4(nv._v4) {} 
    124167 
    125             NewVertex(float f1,osg::Vec3* v1, 
     168            NewVertex(osg::Vec3* vx, 
     169                      float f1,osg::Vec3* v1, 
    126170                      float f2,osg::Vec3* v2, 
    127171                      float f3,osg::Vec3* v3, 
    128172                      float f4,osg::Vec3* v4): 
     173                _vpos(vx), 
    129174                _f1(f1), 
    130175                _v1(v1), 
     
    135180                _f4(f4), 
    136181                _v4(v4) {} 
     182 
     183            osg::Vec3  *_vpos; // added gwm Jan 2004 the vertex coords s.t. NewVertex can be used in a std::vector 
    137184         
    138185            float       _f1; 
     
    150197        }; 
    151198         
    152         typedef std::map<osg::Vec3*,NewVertex> NewVertexList; 
     199        //change NewVertexList from std::map<osg::Vec3*,NewVertex> NewVertexList; 
     200        // because this has undefined order of insertion for new vertices.  
     201        // which occasionally corrupted the texture mapping. 
     202        typedef std::vector<NewVertex> NewVertexList; 
    153203        typedef std::vector<Vec3d*> Vec3dList; 
    154204 
     
    159209        GLenum          _errorCode; 
    160210 
     211        /** winding rule, which parts will become solid */ 
     212        WindingType _wtype;  
     213 
     214        /** tesselation rule, which parts will become solid */ 
     215        TesselationType _ttype; 
     216 
     217        bool _boundaryOnly; // see gluTessProperty - if true: make the boundary edges only. 
     218 
     219        /** number of vertices that are part of the 'original' set of contours */ 
     220        unsigned int _numberVerts; 
     221 
     222        /** List of primitives that define the contours */ 
     223        osg::Geometry::PrimitiveSetList                _Contours; 
     224 
     225        /** count number of primitives in a geometry to get right no. of norms/colurs etc for per_primitive attributes. */ 
     226        unsigned int _index; 
    161227}; 
    162228 
  • OpenSceneGraph/trunk/src/osgUtil/Tesselator.cpp

    r2726 r3209  
    2020using namespace osgUtil; 
    2121 
    22 Tesselator::Tesselator() 
     22 
     23Tesselator::Tesselator() : 
     24    _wtype(TESS_WINDING_ODD), 
     25    _ttype(TESS_TYPE_POLYGONS), 
     26    _boundaryOnly(false), _numberVerts(0)  
    2327{ 
    2428    _tobj = 0; 
    2529    _errorCode = 0; 
     30    _index=0; 
    2631} 
    2732 
     
    146151 
    147152}; 
    148              
    149  
    150 void Tesselator::retesselatePolygons(osg::Geometry& geom) 
    151 { 
     153 
     154void Tesselator::retesselatePolygons(osg::Geometry &geom) 
     155{ 
     156    // turn the contour list into primitives, a little like tesselator does but more generally 
    152157    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); 
     158     
    153159    if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return; 
    154160 
     
    167173    } 
    168174 
    169     // process the primitives  
    170     int noPrimitiveAtStart = geom.getPrimitiveSetList().size(); 
    171     for(int primNo=0;primNo<noPrimitiveAtStart;++primNo) 
    172     { 
    173         osg::PrimitiveSet* primitive = geom.getPrimitiveSetList()[primNo].get(); 
    174         if (primitive->getMode()==osg::PrimitiveSet::POLYGON && primitive->getNumIndices()>3) 
    175         { 
    176             beginTesselation(); 
    177             beginContour(); 
    178  
    179             switch(primitive->getType()) 
    180             { 
    181                 case(osg::PrimitiveSet::DrawArraysPrimitiveType): 
     175    if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) _numberVerts=0; // 09.04.04 GWM reset tesselator 
     176    // the reset is needed by the flt loader which reuses a tesselator for triangulating polygons. 
     177    // as such it might be reset by other loaders/developers in future. 
     178    _index=0; // reset the counter for indexed vertices 
     179    if (!_numberVerts) { 
     180        _numberVerts=geom.getVertexArray()->getNumElements(); 
     181        // save the contours for complex (winding rule) tesselations 
     182        _Contours=geom.getPrimitiveSetList(); 
     183    } 
     184 
     185    // now cut out vertex attributes added on any previous tesselation 
     186    reduceArray(geom.getVertexArray(), _numberVerts); 
     187    reduceArray(geom.getColorArray(), _numberVerts); 
     188    reduceArray(geom.getNormalArray(), _numberVerts); 
     189    reduceArray(geom.getFogCoordArray(), _numberVerts); 
     190    for(unsigned int unit1=0;unit1<geom.getNumTexCoordArrays();++unit1) 
     191    { 
     192        reduceArray(geom.getTexCoordArray(unit1), _numberVerts); 
     193    } 
     194 
     195    // remove the existing primitives. 
     196    unsigned int nprimsetoriginal= geom.getNumPrimitiveSets(); 
     197    if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal); 
     198 
     199    // the main difference from osgUtil::tesselator for Geometry sets of multiple contours is that the begin/end tesselation 
     200    // occurs around the whole set of contours. 
     201    if (_ttype==TESS_TYPE_GEOMETRY) { 
     202        beginTesselation(); 
     203        gluTessProperty(_tobj, GLU_TESS_WINDING_RULE, _wtype); 
     204        gluTessProperty(_tobj, GLU_TESS_BOUNDARY_ONLY , _boundaryOnly); 
     205    } 
     206    // process all the contours into the tesselator 
     207    int noContours = _Contours.size(); 
     208    for(int primNo=0;primNo<noContours;++primNo) 
     209    { 
     210        osg::ref_ptr<osg::PrimitiveSet> primitive = _Contours[primNo].get(); 
     211        if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) { 
     212            if (primitive->getMode()==osg::PrimitiveSet::POLYGON ||_ttype==TESS_TYPE_DRAWABLE)  { 
     213                beginTesselation(); 
     214                addContour(primitive.get(), vertices); 
     215                endTesselation(); 
     216 
     217                collectTesselation(geom); 
     218            } else { // copy the contour primitive as it is not being tesselated 
     219                geom.addPrimitiveSet(primitive.get()); 
     220            } 
     221        } else { 
     222            if (primitive->getMode()==osg::PrimitiveSet::POLYGON || 
     223                primitive->getMode()==osg::PrimitiveSet::QUADS || 
     224                primitive->getMode()==osg::PrimitiveSet::TRIANGLES || 
     225                primitive->getMode()==osg::PrimitiveSet::LINE_LOOP || 
     226                primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP || 
     227                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN || 
     228                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP) 
     229            { 
     230                addContour(primitive.get(), vertices); 
     231            } else { // copy the contour primitive as it is not being tesselated 
     232                // in this case points, lines or line_strip 
     233                geom.addPrimitiveSet(primitive.get()); 
     234            } 
     235        } 
     236    } 
     237    if (_ttype==TESS_TYPE_GEOMETRY) { 
     238        endTesselation(); 
     239     
     240        collectTesselation(geom);     
     241    } 
     242} 
     243 
     244void Tesselator::addContour(osg::PrimitiveSet* primitive, osg::Vec3Array* vertices) 
     245{ 
     246    // adds a single primitive as a contour. 
     247    beginContour(); 
     248    unsigned int nperprim=0; // number of vertices per primitive 
     249    if (primitive->getMode()==osg::PrimitiveSet::QUADS) nperprim=4; 
     250    if (primitive->getMode()==osg::PrimitiveSet::TRIANGLES) nperprim=3; 
     251    unsigned int idx=0; 
     252     
     253    switch(primitive->getType()) 
     254    { 
     255    case(osg::PrimitiveSet::DrawArraysPrimitiveType): 
     256        { 
     257            unsigned int i; 
     258            osg::DrawArrays* drawArray = static_cast<osg::DrawArrays*>(primitive); 
     259            unsigned int first = drawArray->getFirst();  
     260            unsigned int last = first+drawArray->getCount(); 
     261 
     262            switch (primitive->getMode()) { 
     263            case osg::PrimitiveSet::QUADS: 
     264            case osg::PrimitiveSet::TRIANGLES: 
     265            case osg::PrimitiveSet::POLYGON: 
     266            case osg::PrimitiveSet::LINE_LOOP: 
     267            case osg::PrimitiveSet::TRIANGLE_FAN: 
    182268                { 
    183                     osg::DrawArrays* drawArray = static_cast<osg::DrawArrays*>(primitive); 
    184                     unsigned int first = drawArray->getFirst();  
    185                     unsigned int last = first+drawArray->getCount(); 
    186                     for(unsigned int i=first;i<last;++i) 
     269                    for(i=first;i<last;++i, idx++) 
     270                    { 
     271                        addVertex(&((*vertices)[i])); 
     272                        if (nperprim>0 && i<last-1 && idx%nperprim==nperprim-1) { 
     273                            endContour(); 
     274                            beginContour(); 
     275                        } 
     276                    } 
     277                } 
     278                break; 
     279            case osg::PrimitiveSet::QUAD_STRIP: 
     280                { // always has an even number of vertices 
     281                    for( i=first;i<last;i+=2) 
     282                    { // 0,2,4... 
     283                        addVertex(&((*vertices)[i])); 
     284                    } 
     285                    for(i=last-1;i>=first;i-=2) 
     286                    { // ...5,3,1 
     287                        addVertex(&((*vertices)[i])); 
     288                    } 
     289                } 
     290                break; 
     291            case osg::PrimitiveSet::TRIANGLE_STRIP: 
     292                { 
     293                    for( i=first;i<last;i+=2) 
     294                    {// 0,2,4,... 
     295                        addVertex(&((*vertices)[i])); 
     296                    } 
     297                    for(i=((last-first)%2)?(last-2):(last-1) ;i>first&& i<last;i-=2) 
    187298                    { 
    188299                        addVertex(&((*vertices)[i])); 
    189300                    } 
    190                     break; 
    191                 } 
    192                 case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType): 
     301                } 
     302                break; 
     303            default: // lines, points, line_strip 
    193304                { 
    194                     osg::DrawElementsUByte* drawElements = static_cast<osg::DrawElementsUByte*>(primitive); 
    195                     for(osg::DrawElementsUByte::iterator indexItr=drawElements->begin(); 
    196                         indexItr!=drawElements->end(); 
    197                         ++indexItr) 
     305                    for(i=first;i<last;++i, idx++) 
    198306                    { 
    199                         addVertex(&((*vertices)[*indexItr])); 
    200                     } 
    201                     break; 
    202                 } 
    203                 case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType): 
    204                 { 
    205                     osg::DrawElementsUShort* drawElements = static_cast<osg::DrawElementsUShort*>(primitive); 
    206                     for(osg::DrawElementsUShort::iterator indexItr=drawElements->begin(); 
    207                         indexItr!=drawElements->end(); 
    208                         ++indexItr) 
    209                     { 
    210                         addVertex(&((*vertices)[*indexItr])); 
    211                     } 
    212                     break; 
    213                 } 
    214                 case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType): 
    215                 { 
    216                     osg::DrawElementsUInt* drawElements = static_cast<osg::DrawElementsUInt*>(primitive); 
    217                     for(osg::DrawElementsUInt::iterator indexItr=drawElements->begin(); 
    218                         indexItr!=drawElements->end(); 
    219                         ++indexItr) 
    220                     { 
    221                         addVertex(&((*vertices)[*indexItr])); 
    222                     } 
    223                     break; 
    224                 } 
    225                 default: 
    226                     break; 
    227             } 
    228              
    229             endContour(); 
    230             endTesselation(); 
    231              
    232             typedef std::map<osg::Vec3*,unsigned int> VertexPtrToIndexMap; 
    233             VertexPtrToIndexMap vertexPtrToIndexMap; 
    234              
    235             // populate the VertexPtrToIndexMap. 
    236             for(unsigned int vi=0;vi<vertices->size();++vi) 
    237             { 
    238                 vertexPtrToIndexMap[&((*vertices)[vi])] = vi; 
    239             } 
    240              
    241             if (!_newVertexList.empty()) 
    242             { 
    243  
    244                 osg::Vec3Array* normals = NULL; 
    245                 if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX) 
    246                 { 
    247                     normals = geom.getNormalArray(); 
    248                 } 
    249  
    250                 typedef std::vector<osg::Array*> ArrayList; 
    251                 ArrayList arrays; 
    252      
    253                 if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX) 
    254                 { 
    255                     arrays.push_back(geom.getColorArray()); 
    256                 } 
    257                  
    258                 if (geom.getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX) 
    259                 { 
    260                     arrays.push_back(geom.getSecondaryColorArray()); 
    261                 } 
    262  
    263                 if (geom.getFogCoordBinding()==osg::Geometry::BIND_PER_VERTEX) 
    264                 { 
    265                     arrays.push_back(geom.getFogCoordArray()); 
    266                 } 
    267  
    268                 osg::Geometry::ArrayList& tcal = geom.getTexCoordArrayList(); 
    269                 for(osg::Geometry::ArrayList::iterator tcalItr=tcal.begin(); 
    270                     tcalItr!=tcal.end(); 
    271                     ++tcalItr) 
    272                 { 
    273                     if (tcalItr->array.valid())  
    274                     { 
    275                         arrays.push_back(tcalItr->array.get()); 
    276                     } 
    277                 } 
    278  
    279                 // now add any new vertices that are required. 
    280                 for(NewVertexList::iterator itr=_newVertexList.begin(); 
    281                     itr!=_newVertexList.end(); 
    282                     ++itr) 
    283                 { 
    284                     osg::Vec3* vertex = itr->first; 
    285                     NewVertex& newVertex = itr->second; 
    286  
    287                     // assign vertex. 
    288                     vertexPtrToIndexMap[vertex]=vertices->size(); 
    289                     vertices->push_back(*vertex); 
    290                      
    291                     // assign normals 
    292                     if (normals) 
    293                     { 
    294                         osg::Vec3 norm(0.0f,0.0f,0.0f); 
    295                         if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1; 
    296                         if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2; 
    297                         if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3; 
    298                         if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4; 
    299                         norm.normalize(); 
    300                         normals->push_back(norm); 
    301                     } 
    302                      
    303                     if (!arrays.empty()) 
    304                     { 
    305                         InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1], 
    306                                               newVertex._f2,vertexPtrToIndexMap[newVertex._v2], 
    307                                               newVertex._f3,vertexPtrToIndexMap[newVertex._v3], 
    308                                               newVertex._f4,vertexPtrToIndexMap[newVertex._v4]); 
    309  
    310                                                   // assign the rest of the attributes. 
    311                         for(ArrayList::iterator aItr=arrays.begin(); 
    312                             aItr!=arrays.end(); 
    313                             ++aItr) 
    314                         { 
    315                             (*aItr)->accept(inv); 
     307                        addVertex(&((*vertices)[i])); 
     308                        if (nperprim>0 && i<last-1 && idx%nperprim==nperprim-1) { 
     309                            endContour(); 
     310                            beginContour(); 
    316311                        } 
    317312                    } 
    318313                } 
    319  
    320             } 
     314                break; 
     315            } 
     316            break; 
     317        } 
     318    case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType): 
     319        { 
     320            osg::DrawElementsUByte* drawElements = static_cast<osg::DrawElementsUByte*>(primitive); 
     321            for(osg::DrawElementsUByte::iterator indexItr=drawElements->begin(); 
     322            indexItr!=drawElements->end(); 
     323            ++indexItr, idx++) 
     324            { 
     325                addVertex(&((*vertices)[*indexItr])); 
     326                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) { 
     327                    endContour(); 
     328                    beginContour(); 
     329                } 
     330            } 
     331            break; 
     332        } 
     333    case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType): 
     334        { 
     335            osg::DrawElementsUShort* drawElements = static_cast<osg::DrawElementsUShort*>(primitive); 
     336            for(osg::DrawElementsUShort::iterator indexItr=drawElements->begin(); 
     337            indexItr!=drawElements->end(); 
     338            ++indexItr, idx++) 
     339            { 
     340                addVertex(&((*vertices)[*indexItr])); 
     341                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) { 
     342                    endContour(); 
     343                    beginContour(); 
     344                } 
     345            } 
     346            break; 
     347        } 
     348    case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType): 
     349        { 
     350            osg::DrawElementsUInt* drawElements = static_cast<osg::DrawElementsUInt*>(primitive); 
     351            for(osg::DrawElementsUInt::iterator indexItr=drawElements->begin(); 
     352            indexItr!=drawElements->end(); 
     353            ++indexItr, idx++) 
     354            { 
     355                addVertex(&((*vertices)[*indexItr])); 
     356                if (nperprim>0 && indexItr!=drawElements->end() && idx%nperprim==nperprim-1) { 
     357                    endContour(); 
     358                    beginContour(); 
     359                } 
     360            } 
     361            break; 
     362        } 
     363    default: 
     364        break; 
     365    } 
     366     
     367    endContour(); 
     368} 
     369 
     370void Tesselator::handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap) 
     371{ 
     372    if (!_newVertexList.empty()) 
     373    { 
     374         
     375        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); 
     376        osg::Vec3Array* normals = NULL; 
     377        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX) 
     378        { 
     379            normals = geom.getNormalArray(); 
     380        } 
     381         
     382        typedef std::vector<osg::Array*> ArrayList; 
     383        ArrayList arrays; 
     384         
     385        if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX) 
     386        { 
     387            arrays.push_back(geom.getColorArray()); 
     388        } 
     389         
     390        if (geom.getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX) 
     391        { 
     392            arrays.push_back(geom.getSecondaryColorArray()); 
     393        } 
     394         
     395        if (geom.getFogCoordBinding()==osg::Geometry::BIND_PER_VERTEX) 
     396        { 
     397            arrays.push_back(geom.getFogCoordArray()); 
     398        } 
     399         
     400        osg::Geometry::ArrayList& tcal = geom.getTexCoordArrayList(); 
     401        for(osg::Geometry::ArrayList::iterator tcalItr=tcal.begin(); 
     402        tcalItr!=tcal.end(); 
     403        ++tcalItr) 
     404        { 
     405            if (tcalItr->array.valid())  
     406            { 
     407                arrays.push_back(tcalItr->array.get()); 
     408            } 
     409        } 
     410         
     411        // now add any new vertices that are required. 
     412        for(NewVertexList::iterator itr=_newVertexList.begin(); 
     413        itr!=_newVertexList.end(); 
     414        ++itr) 
     415        { 
     416            NewVertex& newVertex = (*itr); 
     417            osg::Vec3* vertex = newVertex._vpos; 
    321418             
     419            // assign vertex. 
     420            vertexPtrToIndexMap[vertex]=vertices->size(); 
     421            vertices->push_back(*vertex); 
    322422             
    323             // we don't properly handle per primitive and per primitive_set bindings yet 
    324             // will need to address this soon. Robert Oct 2002. 
    325             { 
    326                 osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets 
    327                 int iprim=0; 
    328                 if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE || 
    329                     geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) 
     423            // assign normals 
     424            if (normals) 
     425            { 
     426                osg::Vec3 norm(0.0f,0.0f,0.0f); 
     427                if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1; 
     428                if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2; 
     429                if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3; 
     430                if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4; 
     431                norm.normalize(); 
     432                normals->push_back(norm); 
     433            } 
     434             
     435            if (!arrays.empty()) 
     436            { 
     437                InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1], 
     438                    newVertex._f2,vertexPtrToIndexMap[newVertex._v2], 
     439                    newVertex._f3,vertexPtrToIndexMap[newVertex._v3], 
     440                    newVertex._f4,vertexPtrToIndexMap[newVertex._v4]); 
     441                 
     442                // assign the rest of the attributes. 
     443                for(ArrayList::iterator aItr=arrays.begin(); 
     444                aItr!=arrays.end(); 
     445                ++aItr) 
    330446                { 
    331                     normals = geom.getNormalArray(); // GWM Sep 2002 
    332                 } 
    333                  // GWM Dec 2003 - nneded to add colours for extra facets 
    334                 osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4 
    335                 osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3 
    336                 if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE/* || 
    337                     geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET*/) 
    338                 { 
    339                     Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours 
    340                     switch (colours->getType()) { 
    341                     case osg::Array::Vec4ArrayType: 
    342                         cols4=dynamic_cast<osg::Vec4Array *> (colours); 
    343                         break; 
    344                     case osg::Array::Vec3ArrayType: 
    345                         cols3=dynamic_cast<osg::Vec3Array *> (colours); 
    346                         break; 
    347                     default: 
    348                         // not handled cases  
    349                         break; 
    350                     } 
    351  
    352                 } 
    353                 // GWM Dec 2003 - these holders need to go outside the loop to  
    354                 // retain the flat shaded colour &/or normal for each tesselated polygon 
    355                 osg::Vec3 norm(0.0f,0.0f,0.0f); 
    356                 osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f); 
    357                 osg::Vec3 primCol3(0.0f,0.0f,0.0f); 
    358                 for(PrimList::iterator primItr=_primList.begin(); 
    359                 primItr!=_primList.end(); 
    360                 ++primItr) 
    361                 { 
    362                     Prim* prim = primItr->get(); 
    363                     osg::Vec3 norm(0.0f,0.0f,0.0f); 
    364                      
    365                     osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode); 
    366                     for(Prim::VecList::iterator vitr=prim->_vertices.begin(); 
    367                     vitr!=prim->_vertices.end(); 
    368                     ++vitr) 
    369                     { 
    370                         elements->push_back(vertexPtrToIndexMap[*vitr]); 
    371                     } 
    372                      
    373                     if (primItr==_primList.begin())  
    374                     {   // first new primitive so overwrite the previous polygon & collect primitive normal & colour. 
    375                         geom.getPrimitiveSetList()[primNo] = elements;                     
    376                         if (normals) { 
    377                             norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal 
    378                         } 
    379                         if (cols4) { 
    380                             primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour 
    381                         } 
    382                         if (cols3) { 
    383                             primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour 
    384                         } 
    385                     } 
    386                     else 
    387                     { 
    388                         // subsequent primitives add to the back of the primitive list, and may have same colour as hte original facet. 
    389                         geom.addPrimitiveSet(elements); 
    390                         if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet 
    391                         if (cols4) cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet 
    392                         if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet 
    393                         if (prim->_mode==GL_TRIANGLES) { // also need one per triangle? 
    394                             int ntris=elements->getNumIndices()/3; 
    395                             for (int ii=1; ii<ntris; ii++) { 
    396                                 if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet 
    397                                 if (cols4) cols4->push_back(primCol4); 
    398                             } 
    399                         } 
    400                 //        osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl;  
    401                     } 
    402                     iprim++; // GWM Sep 2002 count which normal we should use 
    403                 } 
    404             } 
    405              
    406         } 
    407          
    408     } 
     447                    (*aItr)->accept(inv); 
     448                } 
     449            } 
     450        } 
     451         
     452    } 
     453     
    409454} 
    410455 
     
    426471void Tesselator::combine(osg::Vec3* vertex,void* vertex_data[4],GLfloat weight[4]) 
    427472{ 
    428     _newVertexList[vertex]=NewVertex(weight[0],(Vec3*)vertex_data[0], 
     473    _newVertexList.push_back(NewVertex(vertex, 
     474                                    weight[0],(Vec3*)vertex_data[0], 
    429475                                     weight[1],(Vec3*)vertex_data[1], 
    430476                                     weight[2],(Vec3*)vertex_data[2], 
    431                                      weight[3],(Vec3*)vertex_data[3]); 
     477                                     weight[3],(Vec3*)vertex_data[3])); 
    432478} 
    433479 
     
    470516    ((Tesselator*)userData)->error(errorCode); 
    471517} 
     518 
     519void Tesselator::reduceArray(osg::Array * cold, const unsigned int nnu) 
     520{ // shrinks size of array to N 
     521    if (cold && cold->getNumElements()>nnu) { 
     522        osg::Vec2Array* v2arr = NULL; 
     523        osg::Vec3Array* v3arr = NULL; 
     524        osg::Vec4Array* v4arr = NULL; 
     525        switch (cold->getType()) { 
     526        case osg::Array::Vec2ArrayType: { 
     527            v2arr = dynamic_cast<osg::Vec2Array*>(cold); 
     528            osg::Vec2Array::iterator itr=v2arr->begin()+nnu; 
     529            (*v2arr).erase(itr, v2arr->end()); 
     530                                        } 
     531            break; 
     532        case osg::Array::Vec3ArrayType: { 
     533            v3arr = dynamic_cast<osg::Vec3Array*>(cold); 
     534            osg::Vec3Array::iterator itr=v3arr->begin()+nnu; 
     535            (*v3arr).erase(itr, v3arr->end()); 
     536                                        } 
     537            break; 
     538        case osg::Array::Vec4ArrayType: { 
     539            v4arr = dynamic_cast<osg::Vec4Array*>(cold); 
     540            osg::Vec4Array::iterator itr=v4arr->begin()+nnu; 
     541            (*v4arr).erase(itr, v4arr->end()); 
     542                                        } 
     543            break; 
     544        default: // should also handle:ArrayType' ByteArrayType' ShortArrayType' IntArrayType'  
     545        // `UShortArrayType'  `UIntArrayType'  `UByte4ArrayType'  `FloatArrayType'  
     546            break; 
     547        } 
     548    } 
     549} 
     550 
     551unsigned int _computeNumberOfPrimitives(const osg::Geometry& geom) 
     552{ 
     553 
     554    unsigned int totalNumberOfPrimitives = 0; 
     555     
     556    for(Geometry::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin(); 
     557        itr!=geom.getPrimitiveSetList().end(); 
     558        ++itr) 
     559    { 
     560        const PrimitiveSet* primitiveset = itr->get(); 
     561        GLenum mode=primitiveset->getMode(); 
     562 
     563        unsigned int primLength; 
     564        switch(mode) 
     565        { 
     566            case(GL_POINTS):    primLength=1; break; 
     567            case(GL_LINES):     primLength=2; break; 
     568            case(GL_TRIANGLES): primLength=3; break; 
     569            case(GL_QUADS):     primLength=4; break; 
     570            default:            primLength=0; break; // compute later when =0. 
     571        } 
     572 
     573        // draw primtives by the more flexible "slow" path, 
     574        // sending OpenGL glBegin/glVertex.../glEnd(). 
     575        switch(primitiveset->getType()) 
     576        { 
     577            case(PrimitiveSet::DrawArrayLengthsPrimitiveType): 
     578            { 
     579 
     580                const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset); 
     581                for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin(); 
     582                    primItr!=drawArrayLengths->end(); 
     583                    ++primItr) 
     584                { 
     585                    if (primLength==0) totalNumberOfPrimitives += 1; 
     586                    else totalNumberOfPrimitives += *primItr/primLength; // Dec 2003 - increment not set 
     587                } 
     588                break; 
     589            } 
     590            default: 
     591            { 
     592                if (primLength==0) totalNumberOfPrimitives += 1; 
     593                else totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; 
     594            } 
     595        } 
     596    } 
     597 
     598    return totalNumberOfPrimitives; 
     599} 
     600// 
     601void Tesselator::collectTesselation(osg::Geometry &geom) 
     602{ 
     603    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); 
     604    VertexPtrToIndexMap vertexPtrToIndexMap; 
     605     
     606    // populate the VertexPtrToIndexMap. 
     607    for(unsigned int vi=0;vi<vertices->size();++vi) 
     608    { 
     609        vertexPtrToIndexMap[&((*vertices)[vi])] = vi; 
     610    } 
     611     
     612    handleNewVertices(geom, vertexPtrToIndexMap); 
     613     
     614    // we don't properly handle per primitive and per primitive_set bindings yet 
     615    // will need to address this soon. Robert Oct 2002. 
     616    { 
     617        osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets 
     618        int iprim=0; 
     619        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE || 
     620            geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) 
     621        { 
     622            normals = geom.getNormalArray(); // GWM Sep 2002 
     623        } 
     624        // GWM Dec 2003 - needed to add colours for extra facets 
     625        osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4 
     626        osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3 
     627        if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE || 
     628              geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) 
     629        { 
     630              Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours 
     631              switch (colours->getType()) { 
     632              case osg::Array::Vec4ArrayType: 
     633                  cols4=dynamic_cast<osg::Vec4Array *> (colours); 
     634                  break; 
     635              case osg::Array::Vec3ArrayType: 
     636                  cols3=dynamic_cast<osg::Vec3Array *> (colours); 
     637                  break; 
     638              default: 
     639                  break; 
     640              } 
     641               
     642        } 
     643        // GWM Dec 2003 - these holders need to go outside the loop to  
     644        // retain the flat shaded colour &/or normal for each tesselated polygon 
     645        osg::Vec3 norm(0.0f,0.0f,0.0f); 
     646        osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f); 
     647        osg::Vec3 primCol3(0.0f,0.0f,0.0f); 
     648 
     649        for(PrimList::iterator primItr=_primList.begin(); 
     650        primItr!=_primList.end(); 
     651        ++primItr, ++_index) 
     652        { 
     653              Prim* prim = primItr->get(); 
     654               
     655              osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode); 
     656              for(Prim::VecList::iterator vitr=prim->_vertices.begin(); 
     657              vitr!=prim->_vertices.end(); 
     658              ++vitr) 
     659              { 
     660                  elements->push_back(vertexPtrToIndexMap[*vitr]); 
     661              } 
     662               
     663              // add to the drawn primitive list. 
     664              geom.addPrimitiveSet(elements); 
     665              if (primItr==_primList.begin())  
     666              {   // first primitive so collect primitive normal & colour. 
     667                  if (normals) { 
     668                      norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal 
     669                  } 
     670                  if (cols4) { 
     671                      primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour 
     672                    if (_index>=cols4->size()) { 
     673                        cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet 
     674                    } 
     675                  } 
     676                  if (cols3) { 
     677                      primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour 
     678                    if (_index>=cols4->size()) { 
     679                        cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet 
     680                    } 
     681                  } 
     682              } 
     683              else 
     684              { // later primitives use same colour 
     685                  if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet 
     686                  if (cols4 && _index>=cols4->size()) { 
     687                    cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet 
     688                  } 
     689                  if (cols3 && _index>=cols3->size()) { 
     690                    if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet 
     691                  } 
     692                  if (prim->_mode==GL_TRIANGLES) { 
     693                      int ntris=elements->getNumIndices()/3; 
     694                      if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET || 
     695                          geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set. 
     696                          for (int ii=1; ii<ntris; ii++) { 
     697                              if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet 
     698                          } 
     699                      } 
     700                      if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET || 
     701                          geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set. 
     702                          for (int ii=1; ii<ntris; ii++) { 
     703                              if (cols3 && _index>=cols3->size()) { 
     704                                  if (cols3) cols3->push_back(primCol3); 
     705                              } 
     706                              if (cols4 && _index>=cols4->size()) { 
     707                                  if (cols4) cols4->push_back(primCol4); 
     708                              } 
     709                              _index++; 
     710                          } 
     711                      } 
     712                  } 
     713                  //        osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl;  
     714              } 
     715              iprim++; // GWM Sep 2002 count which normal we should use 
     716        } 
     717    } 
     718}