Changeset 3221

Show
Ignore:
Timestamp:
08/03/04 09:31:33 (10 years ago)
Author:
robert
Message:

Changed the static array syntax to solve VS.NET compile warnigns, changed
the binding of the normals, and changed the name of the textures used.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgtesselate/osgtesselate.cpp

    r3209 r3221  
    1616 * the tesselator has new member fuinctions 
    1717 setTesselationType(osgUtil::Tesselator::TESS_TYPE_xxx); 
    18         tscx->setBoundaryOnly(bool); 
    19         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_xxx);  
     18    tscx->setBoundaryOnly(bool); 
     19    tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_xxx);  
    2020 * for winding rules: See the red book chap 13. 
    2121 */ 
     
    3333 
    3434class tesselateDemoGeometry : public osg::Geometry, public osgUtil::Tesselator { 
    35         // We add the Tesselator to the geometry because we want to access the 
    36         // tesselatable contours again;  you can apply a tesselator to a Geometry  
    37         // to produce exactly a required tesselation once only, and then  
    38         // the contours could be discarded since the geometry does not need to be retesselated. 
     35    // We add the Tesselator to the geometry because we want to access the 
     36    // tesselatable contours again;  you can apply a tesselator to a Geometry  
     37    // to produce exactly a required tesselation once only, and then  
     38    // the contours could be discarded since the geometry does not need to be retesselated. 
    3939public: 
    40         tesselateDemoGeometry() {}; 
     40    tesselateDemoGeometry() {}; 
    4141 
    4242protected: 
    43         virtual ~tesselateDemoGeometry() {}; 
     43    virtual ~tesselateDemoGeometry() {}; 
    4444}; 
    4545 
    46 osg::Geometry *makePolsTwo (void) { 
    47         // an example of using current geometry contours to create next tesselation 
    48         // this polygon disappears once the contour rules make no polygons. 
    49         tesselateDemoGeometry *gtess= new tesselateDemoGeometry; 
    50         int i; 
    51         osg::Vec3Array *coords = new osg::Vec3Array; 
    52         osg::Vec3Array *nrms = new osg::Vec3Array; 
    53         osg::Vec2Array *tcs = new osg::Vec2Array; 
    54         osg::Vec3 nrm(0,-1,0); 
    55         static GLdouble quadstrip[8][3] = 
    56         {1900.0, 1130.0, 0.0, 2100.0, 1130.0, 0.0,  
    57         1900.0, 1350.0, 0.0, 1950.0, 1350.0, 0.0,  
    58         1900.0, 1550.0, 0.0, 2000.0, 1550.0, 0.0,  
    59         1900.0, 1750.0, 0.0, 2400.0, 1750.0, 0.0}; 
    60         static GLdouble innerquadstrip[8][3] = 
    61         {2000.0, 1230.0, 0.0, 2050.0, 1230.0, 0.0,  
    62         1920.0, 1350.0, 0.0, 1940.0, 1350.0, 0.0,  
    63         1920.0, 1550.0, 0.0, 1980.0, 1550.0, 0.0,  
    64         2000.0, 1650.0, 0.0, 2400.0, 1650.0, 0.0}; 
    65         // add one large quadstrip  
    66         for (i = 0; i < 8; i++) { 
    67                 coords->push_back(osg::Vec3(quadstrip[i][0],quadstrip[i][2],quadstrip[i][1])); 
    68                 tcs->push_back(osg::Vec2(quadstrip[i][0],quadstrip[i][1])/200.0); 
    69                 nrms->push_back(nrm); 
    70         } 
    71         for (i = 0; i < 8; i++) { 
    72                 coords->push_back(osg::Vec3(innerquadstrip[i][0],innerquadstrip[i][2],innerquadstrip[i][1])); 
    73                 tcs->push_back(osg::Vec2(innerquadstrip[i][0],innerquadstrip[i][1])/200.0); 
    74                 nrms->push_back(nrm); 
    75         } 
    76         gtess->setVertexArray(coords); 
    77         gtess->setNormalArray(nrms); 
    78         gtess->setTexCoordArray(0,tcs); 
    79          
    80         // demonstrate that the tesselator makes textured tesselations 
     46osg::Geometry *makePolsTwo (void)  
     47{ 
     48    // an example of using current geometry contours to create next tesselation 
     49    // this polygon disappears once the contour rules make no polygons. 
     50    tesselateDemoGeometry *gtess= new tesselateDemoGeometry; 
     51    int i; 
     52    osg::Vec3Array *coords = new osg::Vec3Array; 
     53    osg::Vec3Array *nrms = new osg::Vec3Array; 
     54    osg::Vec2Array *tcs = new osg::Vec2Array; 
     55    osg::Vec3 nrm(0,-1,0); 
     56    static GLdouble quadstrip[8][3] = 
     57    { { 1900.0, 1130.0, 0.0 }, 
     58      { 2100.0, 1130.0, 0.0 },  
     59      { 1900.0, 1350.0, 0.0 }, 
     60      { 1950.0, 1350.0, 0.0 },  
     61      { 1900.0, 1550.0, 0.0 },  
     62      { 2000.0, 1550.0, 0.0 },  
     63      { 1900.0, 1750.0, 0.0 },  
     64      { 2400.0, 1750.0, 0.0 } }; 
     65    static GLdouble innerquadstrip[8][3] = 
     66    { { 2000.0, 1230.0, 0.0 }, 
     67      { 2050.0, 1230.0, 0.0 }, 
     68      { 1920.0, 1350.0, 0.0 }, 
     69      { 1940.0, 1350.0, 0.0 }, 
     70      { 1920.0, 1550.0, 0.0 }, 
     71      { 1980.0, 1550.0, 0.0 },  
     72      { 2000.0, 1650.0, 0.0 }, 
     73      { 2400.0, 1650.0, 0.0 } }; 
     74     
     75    // add one large quadstrip  
     76    for (i = 0; i < 8; i++) 
     77    { 
     78        coords->push_back(osg::Vec3(quadstrip[i][0],quadstrip[i][2],quadstrip[i][1])); 
     79        tcs->push_back(osg::Vec2(quadstrip[i][0],quadstrip[i][1])/200.0); 
     80        nrms->push_back(nrm); 
     81    } 
     82    for (i = 0; i < 8; i++) { 
     83        coords->push_back(osg::Vec3(innerquadstrip[i][0],innerquadstrip[i][2],innerquadstrip[i][1])); 
     84        tcs->push_back(osg::Vec2(innerquadstrip[i][0],innerquadstrip[i][1])/200.0); 
     85        nrms->push_back(nrm); 
     86    } 
     87    gtess->setVertexArray(coords); 
     88    gtess->setNormalArray(nrms); 
     89    gtess->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
     90    gtess->setTexCoordArray(0,tcs); 
     91     
     92    // demonstrate that the tesselator makes textured tesselations 
    8193    osg::StateSet* stateset = new osg::StateSet(); 
    82          
    83     osg::Image* image = osgDB::readImageFile("Images/osg_posy.png"); 
     94     
     95    osg::Image* image = osgDB::readImageFile("Cubemap_snow/posy.jpg"); 
    8496    if (image) 
    8597    { 
    86                 osg::Texture2D* texture = new osg::Texture2D; 
    87                 texture->setImage(image); 
    88                 stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
    89     } 
    90         gtess->setStateSet( stateset ); 
    91          
    92         int nstart=0; 
    93         // The derived class tesselateDemoGeometry retains the original contours for re-use. 
    94         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,nstart,8));nstart+=8; 
    95         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,nstart,8));nstart+=8; 
    96  
    97         gtess->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
    98         gtess->setBoundaryOnly(true); 
    99         gtess->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); // so that first change in wind type makes the commonest tesselation - ODD. 
    100          
    101         return gtess; 
     98        osg::Texture2D* texture = new osg::Texture2D; 
     99        texture->setImage(image); 
     100        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
     101    } 
     102    gtess->setStateSet( stateset ); 
     103     
     104    int nstart=0; 
     105    // The derived class tesselateDemoGeometry retains the original contours for re-use. 
     106    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,nstart,8));nstart+=8; 
     107    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,nstart,8));nstart+=8; 
     108 
     109    gtess->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
     110    gtess->setBoundaryOnly(true); 
     111    gtess->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); // so that first change in wind type makes the commonest tesselation - ODD. 
     112     
     113    return gtess; 
    102114} 
    103115 
    104 osg::Geometry *makeSideWall (const float xpos) { 
    105         // demonstrate making a rectangular 'wall' with 2 holes in it. 
    106         osg::Geometry *gtess= new osg::Geometry; 
    107         int i; 
    108         osg::Vec3Array *coords = new osg::Vec3Array; 
    109         osg::Vec3Array *nrms = new osg::Vec3Array; 
    110         osg::Vec2Array *tcs = new osg::Vec2Array; 
    111         osg::Vec3 nrm(0,0,-1); 
    112         // front wall 
    113         static GLdouble wall[4][2] = 
    114         {       1130.0, 0.0, 1130.0, 300.0,  
    115                 1340.0,300.0, 1340.0,0.0}; 
    116         gtess->setVertexArray(coords); 
    117         gtess->setNormalArray(nrms); 
    118         gtess->setTexCoordArray(0,tcs); 
    119  
    120         for (i = 0; i < 4; i++) { 
    121                 coords->push_back(osg::Vec3(xpos,wall[i][1],wall[i][0])); 
    122                 tcs->push_back(osg::Vec2(wall[i][1],wall[i][0])/100.0); 
    123                 nrms->push_back(nrm); 
    124         } 
    125         int nstart=0; 
    126  
    127         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,4));nstart+=4; 
    128         for (i = 0; i < 24; i++) { // make an ellipse hole 
    129                 float y=150+50*cos(i*2*osg::PI/24.0); 
    130                 float z=1300+30* sin(i*2*osg::PI/24.0); 
    131                 coords->push_back(osg::Vec3(xpos,y,z)); 
    132                 tcs->push_back(osg::Vec2(y,z)/100.0); 
    133                 nrms->push_back(nrm); 
    134         } 
    135         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,24));nstart+=24; 
    136         for (i = 0; i < 5; i++) { // make a pentagonal hole 
    137                 float y=150+50*cos(i*2*osg::PI/5.0); 
    138                 float z=1200+40* sin(i*2*osg::PI/5.0); 
    139                 coords->push_back(osg::Vec3(xpos,y,z)); 
    140                 tcs->push_back(osg::Vec2(y,z)/100.0); 
    141                 nrms->push_back(nrm); 
    142         } 
    143         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,5));nstart+=5; 
    144          
    145         // demonstrate that the tesselator makes textured tesselations 
     116osg::Geometry *makeSideWall (const float xpos) 
     117{ 
     118    // demonstrate making a rectangular 'wall' with 2 holes in it. 
     119    osg::Geometry *gtess= new osg::Geometry; 
     120    int i; 
     121    osg::Vec3Array *coords = new osg::Vec3Array; 
     122    osg::Vec3Array *nrms = new osg::Vec3Array; 
     123    osg::Vec2Array *tcs = new osg::Vec2Array; 
     124    osg::Vec3 nrm(-1,0,0); 
     125    // front wall 
     126    static GLdouble wall[4][2] = 
     127    { { 1130.0, 0.0 }, 
     128      { 1130.0, 300.0 } ,  
     129      { 1340.0,300.0 }, 
     130      { 1340.0,0.0 } }; 
     131 
     132    gtess->setVertexArray(coords); 
     133    gtess->setNormalArray(nrms); 
     134    gtess->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
     135    gtess->setTexCoordArray(0,tcs); 
     136 
     137    for (i = 0; i < 4; i++) { 
     138        coords->push_back(osg::Vec3(xpos,wall[i][1],wall[i][0])); 
     139        tcs->push_back(osg::Vec2(wall[i][1],wall[i][0])/100.0); 
     140        nrms->push_back(nrm); 
     141    } 
     142    int nstart=0; 
     143 
     144    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,4));nstart+=4; 
     145    for (i = 0; i < 24; i++) { // make an ellipse hole 
     146        float y=150+50*cos(i*2*osg::PI/24.0); 
     147        float z=1300+30* sin(i*2*osg::PI/24.0); 
     148        coords->push_back(osg::Vec3(xpos,y,z)); 
     149        tcs->push_back(osg::Vec2(y,z)/100.0); 
     150        nrms->push_back(nrm); 
     151    } 
     152    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,24));nstart+=24; 
     153    for (i = 0; i < 5; i++) { // make a pentagonal hole 
     154        float y=150+50*cos(i*2*osg::PI/5.0); 
     155        float z=1200+40* sin(i*2*osg::PI/5.0); 
     156        coords->push_back(osg::Vec3(xpos,y,z)); 
     157        tcs->push_back(osg::Vec2(y,z)/100.0); 
     158        nrms->push_back(nrm); 
     159    } 
     160    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,5));nstart+=5; 
     161     
     162    // demonstrate that the tesselator makes textured tesselations 
    146163    osg::StateSet* stateset = new osg::StateSet(); 
    147          
    148     osg::Image* image = osgDB::readImageFile("Images/osg_posx.png"); 
     164     
     165    osg::Image* image = osgDB::readImageFile("Cubemap_snow/posx.jpg"); 
    149166    if (image) 
    150167    { 
    151                 osg::Texture2D* texture = new osg::Texture2D; 
    152                 texture->setImage(image); 
    153                 stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
    154     } 
    155         gtess->setStateSet( stateset ); 
    156          
    157  
    158         osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator; // the v1.2 multi-contour tesselator. 
    159         // we use the geometry primitives to describe the contours which are tesselated. 
    160         // Winding odd means leave hole in surface where there are 2,4,6... contours circling the point. 
    161         tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
    162         tscx->setBoundaryOnly(false); 
    163         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // so that first change in wind type makes the commonest tesselation - ODD. 
    164          
    165         tscx->retesselatePolygons(*gtess); 
    166          
    167         return gtess; 
     168        osg::Texture2D* texture = new osg::Texture2D; 
     169        texture->setImage(image); 
     170        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
     171    } 
     172    gtess->setStateSet( stateset ); 
     173     
     174 
     175    osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator; // the v1.2 multi-contour tesselator. 
     176    // we use the geometry primitives to describe the contours which are tesselated. 
     177    // Winding odd means leave hole in surface where there are 2,4,6... contours circling the point. 
     178    tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
     179    tscx->setBoundaryOnly(false); 
     180    tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // so that first change in wind type makes the commonest tesselation - ODD. 
     181     
     182    tscx->retesselatePolygons(*gtess); 
     183     
     184    return gtess; 
    168185} 
    169186 
    170187osg::Geometry *makeFrontWall (const float zpos) { 
    171         // an example of using one tesselation to make a 'house' wall 
    172         // describe the wall as a pentagon, then door & 4 windows are further contours 
    173         // tesselate the set of contours to make a 'house wall' from the Boolean-like operations. 
    174         int nstart=0; // counts vertices used for the geometry primitives 
    175  
    176         osg::Geometry *gtess= new osg::Geometry; 
    177         int i; 
    178         osg::Vec3Array *coords = new osg::Vec3Array; 
    179         osg::Vec3Array *nrms = new osg::Vec3Array; 
    180         osg::Vec2Array *tcs = new osg::Vec2Array; 
    181         osg::Vec3 nrm(0,0,-1); 
    182         // front wall 
    183         static GLdouble wall[5][2] = 
    184         {2200.0, 1130.0,  2600.0, 1130.0,   
    185         2600.0, 1340.0, 2400.0, 1440.0, 2200.0, 1340.0}; 
    186         static GLdouble door[4][2] = 
    187         {2360.0, 1130.0, 2440.0, 1130.0,  
    188         2440.0, 1230.0, 2360.0, 1230.0}; 
    189         static GLdouble windows[16][2] = 
    190         {2240.0, 1180.0, 2330.0, 1180.0,  
    191         2330.0, 1220.0, 2240.0, 1220.0,  
    192         2460.0, 1180.0, 2560.0, 1180.0,  
    193         2560.0, 1220.0, 2460.0, 1220.0, 
    194         2240.0, 1280.0, 2330.0, 1280.0,  
    195         2330.0, 1320.0, 2240.0, 1320.0,  
    196         2460.0, 1280.0, 2560.0, 1280.0,  
    197         2560.0, 1320.0, 2460.0, 1320.0}; 
    198  
    199         gtess->setVertexArray(coords); 
    200         gtess->setNormalArray(nrms); 
    201         gtess->setTexCoordArray(0,tcs); 
    202  
    203         // add one large pentagon -the wall  
    204         for (i = 0; i < 5; i++) { 
    205                 coords->push_back(osg::Vec3(wall[i][0],zpos,wall[i][1])); 
    206                 tcs->push_back(osg::Vec2(wall[i][0],wall[i][1])/100.0); 
    207                 nrms->push_back(nrm); 
    208         } 
    209         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,5));nstart+=5; 
    210         // add first hole, a door  
    211         for (i = 0; i < 4; i++) { 
    212                 coords->push_back(osg::Vec3(door[i][0],zpos,door[i][1])); 
    213                 tcs->push_back(osg::Vec2(door[i][0],door[i][1])/100.0); 
    214                 nrms->push_back(nrm); 
    215         } 
    216         // and windows 
    217         for (i = 0; i < 16; i++) { 
    218                 coords->push_back(osg::Vec3(windows[i][0],zpos,windows[i][1])); 
    219                 tcs->push_back(osg::Vec2(windows[i][0],windows[i][1])/100.0); 
    220                 nrms->push_back(nrm); 
    221         } 
    222         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,20));nstart+=20; 
    223  
    224         // demonstrate that the tesselator makes textured tesselations 
     188    // an example of using one tesselation to make a 'house' wall 
     189    // describe the wall as a pentagon, then door & 4 windows are further contours 
     190    // tesselate the set of contours to make a 'house wall' from the Boolean-like operations. 
     191    int nstart=0; // counts vertices used for the geometry primitives 
     192 
     193    osg::Geometry *gtess= new osg::Geometry; 
     194    int i; 
     195    osg::Vec3Array *coords = new osg::Vec3Array; 
     196    osg::Vec3Array *nrms = new osg::Vec3Array; 
     197    osg::Vec2Array *tcs = new osg::Vec2Array; 
     198    osg::Vec3 nrm(0,-1,0); 
     199    // front wall 
     200    static GLdouble wall[5][2] = 
     201    { { 2200.0, 1130.0 }, 
     202      { 2600.0, 1130.0 },   
     203      { 2600.0, 1340.0 },  
     204      { 2400.0, 1440.0 }, 
     205      { 2200.0, 1340.0 } }; 
     206 
     207    static GLdouble door[4][2] = 
     208    { { 2360.0, 1130.0 }, 
     209      { 2440.0, 1130.0 },  
     210      { 2440.0, 1230.0 }, 
     211      { 2360.0, 1230.0 } }; 
     212 
     213    static GLdouble windows[16][2] = 
     214    { { 2240.0, 1180.0 }, 
     215      { 2330.0, 1180.0 },  
     216      { 2330.0, 1220.0 }, 
     217      { 2240.0, 1220.0 },  
     218      { 2460.0, 1180.0 }, 
     219      { 2560.0, 1180.0 },  
     220      { 2560.0, 1220.0 }, 
     221      { 2460.0, 1220.0 }, 
     222      { 2240.0, 1280.0 }, 
     223      { 2330.0, 1280.0 },  
     224      { 2330.0, 1320.0 }, 
     225      { 2240.0, 1320.0 },  
     226      { 2460.0, 1280.0 }, 
     227      { 2560.0, 1280.0 },  
     228      { 2560.0, 1320.0 }, 
     229      { 2460.0, 1320.0 } }; 
     230 
     231    gtess->setVertexArray(coords); 
     232    gtess->setNormalArray(nrms); 
     233    gtess->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
     234    gtess->setTexCoordArray(0,tcs); 
     235 
     236    // add one large pentagon -the wall  
     237    for (i = 0; i < 5; i++) { 
     238        coords->push_back(osg::Vec3(wall[i][0],zpos,wall[i][1])); 
     239        tcs->push_back(osg::Vec2(wall[i][0],wall[i][1])/100.0); 
     240        nrms->push_back(nrm); 
     241    } 
     242    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,5));nstart+=5; 
     243    // add first hole, a door  
     244    for (i = 0; i < 4; i++) { 
     245        coords->push_back(osg::Vec3(door[i][0],zpos,door[i][1])); 
     246        tcs->push_back(osg::Vec2(door[i][0],door[i][1])/100.0); 
     247        nrms->push_back(nrm); 
     248    } 
     249    // and windows 
     250    for (i = 0; i < 16; i++) { 
     251        coords->push_back(osg::Vec3(windows[i][0],zpos,windows[i][1])); 
     252        tcs->push_back(osg::Vec2(windows[i][0],windows[i][1])/100.0); 
     253        nrms->push_back(nrm); 
     254    } 
     255    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,20));nstart+=20; 
     256 
     257    // demonstrate that the tesselator makes textured tesselations 
    225258    osg::StateSet* stateset = new osg::StateSet(); 
    226          
    227     osg::Image* image = osgDB::readImageFile("Images/osg_posy.png"); 
     259     
     260    osg::Image* image = osgDB::readImageFile("Cubemap_snow/posy.jpg"); 
    228261    if (image) 
    229262    { 
    230                 osg::Texture2D* texture = new osg::Texture2D; 
    231                 texture->setImage(image); 
    232                 stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
    233     } 
    234         gtess->setStateSet( stateset ); 
    235          
    236         // We use a Tesselator to produce the tesselation required once only  
    237         // and the contours are discarded. 
    238         osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator; // the v1.2 multi-contour tesselator. 
    239         tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
    240         tscx->setBoundaryOnly(false); 
    241         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // so that first change in wind type makes the commonest tesselation - ODD. 
    242          
    243         tscx->retesselatePolygons(*gtess); 
    244          
    245         return gtess; 
     263        osg::Texture2D* texture = new osg::Texture2D; 
     264        texture->setImage(image); 
     265        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
     266    } 
     267    gtess->setStateSet( stateset ); 
     268     
     269    // We use a Tesselator to produce the tesselation required once only  
     270    // and the contours are discarded. 
     271    osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator; // the v1.2 multi-contour tesselator. 
     272    tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
     273    tscx->setBoundaryOnly(false); 
     274    tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // so that first change in wind type makes the commonest tesselation - ODD. 
     275     
     276    tscx->retesselatePolygons(*gtess); 
     277     
     278    return gtess; 
    246279} 
    247280osg::Geode *makeHouse (void) { 
    248         osg::Geode *gd = new osg::Geode; 
    249         gd->addDrawable(makeFrontWall(0.0)); 
    250         gd->addDrawable(makeFrontWall(300.0)); 
    251         gd->addDrawable(makeSideWall(2200.0)); 
    252         gd->addDrawable(makeSideWall(2600.0)); 
    253         return gd; 
     281    osg::Geode *gd = new osg::Geode; 
     282    gd->addDrawable(makeFrontWall(0.0)); 
     283    gd->addDrawable(makeFrontWall(300.0)); 
     284    gd->addDrawable(makeSideWall(2200.0)); 
     285    gd->addDrawable(makeSideWall(2600.0)); 
     286    return gd; 
    254287} 
    255288osg::Geometry *makePols (void) { 
    256         tesselateDemoGeometry *gtess= new tesselateDemoGeometry; 
    257         int i; 
    258         osg::Vec3Array *coords = new osg::Vec3Array; 
    259         osg::Vec3Array *nrms = new osg::Vec3Array; 
    260         osg::Vec2Array *tcs = new osg::Vec2Array; 
    261         osg::Vec3 nrm(0,-1,0); 
    262         // coordinates from red book code but shifted by 1000 & 2000 for alternate tesselatory things. 
    263         static GLdouble rects[12][3] =  
    264         {50.0, 50.0, 0.0, 300.0, 50.0, 0.0,  
    265         300.0, 300.0, 0.0, 50.0, 300.0, 0.0, 
    266         100.0, 100.0, 0.0, 250.0, 100.0, 0.0,  
    267         250.0, 250.0, 0.0, 100.0, 250.0, 0.0, 
    268         150.0, 150.0, 0.0, 200.0, 150.0, 0.0,  
    269         200.0, 200.0, 0.0, 150.0, 200.0, 0.0}; 
    270         static GLdouble rectsMidanti[12][3] = // the centre 2 contours are traversed opposite order to outer contour. 
    271         {1050.0, 50.0, 0.0, 1300.0, 50.0, 0.0,  
    272         1300.0, 300.0, 0.0, 1050.0, 300.0, 0.0, 
    273         1250.0, 100.0, 0.0, 1100.0, 100.0, 0.0,  
    274         1100.0, 250.0, 0.0, 1250.0, 250.0, 0.0,  
    275         1200.0, 150.0, 0.0, 1150.0, 150.0, 0.0,  
    276         1150.0, 200.0, 0.0, 1200.0, 200.0, 0.0 }; 
    277         static GLdouble spiral[16][3] = // shift by 1000; nb the order of vertices is reversed from that of the red book 
    278         {3400.0, 250.0, 0.0, 3400.0, 50.0, 0.0,  
    279         3050.0, 50.0, 0.0,  3050.0, 400.0, 0.0,  
    280         3350.0, 400.0, 0.0, 3350.0, 100.0, 0.0,  
    281         3100.0, 100.0, 0.0, 3100.0, 350.0, 0.0,  
    282         3300.0, 350.0, 0.0, 3300.0, 150.0, 0.0,  
    283         3150.0, 150.0, 0.0, 3150.0, 300.0, 0.0,  
    284         3250.0, 300.0, 0.0, 3250.0, 200.0, 0.0,  
    285         3200.0, 200.0, 0.0, 3200.0, 250.0, 0.0}; 
    286         static GLdouble quad1[4][3] = // shift by 2000 for next 3 things 
    287         {2050.0, 150.0, 0.0, 2350.0, 150.0, 0.0,  
    288         2350.0, 200.0, 0.0, 2050.0, 200.0, 0.0}; 
    289         static GLdouble quad2[4][3] = 
    290         {2100.0, 100.0, 0.0, 2300.0, 100.0, 0.0,  
    291         2300.0, 350.0, 0.0, 2100.0, 350.0, 0.0}; 
    292         static GLdouble tri[3][3] = 
    293         {2200.0, 50.0, 0.0, 2250.0, 300.0, 0.0, 
    294     2150.0, 300.0, 0.0}; 
    295         static GLdouble quad3[4][3] = 
    296         {100.0, 1100.0, 0.0, 1300.0, 1100.0, 0.0,  
    297         1300.0, 2350.0, 0.0, 100.0, 2350.0, 0.0}; 
    298         static GLdouble quadstrip[8][3] = 
    299         {900.0, 1130.0, 0.0, 1100.0, 1130.0, 0.0,  
    300         900.0, 1350.0, 0.0,  950.0, 1350.0, 0.0,  
    301         900.0, 1550.0, 0.0, 1000.0, 1550.0, 0.0,  
    302         900.0, 1750.0, 0.0, 1400.0, 1750.0, 0.0}; 
    303          
    304         for (i = 0; i < 12; i++) { 
    305                 coords->push_back(osg::Vec3(rects[i][0],rects[i][2],rects[i][1])); 
    306                 tcs->push_back(osg::Vec2(rects[i][0],rects[i][1])/200.0); 
    307                 nrms->push_back(nrm); 
    308         } 
    309         for (i = 0; i < 12; i++) { 
    310                 coords->push_back(osg::Vec3(rectsMidanti[i][0],rectsMidanti[i][2],rectsMidanti[i][1])); 
    311                 tcs->push_back(osg::Vec2(rectsMidanti[i][0],rectsMidanti[i][1])/200.0); 
    312                 nrms->push_back(nrm); 
    313         } 
    314         for (i = 0; i < 16; i++) { // and reverse spiral to make same as that of red book ch 11 
    315                 coords->push_back(osg::Vec3(spiral[15-i][0],spiral[15-i][2],spiral[15-i][1])); 
    316                 tcs->push_back(osg::Vec2(spiral[15-i][0],spiral[15-i][1])/200.0); 
    317                 nrms->push_back(nrm); 
    318         } 
    319         for (i = 0; i < 4; i++) { 
    320                 coords->push_back(osg::Vec3(quad1[i][0],quad1[i][2],quad1[i][1])); 
    321                 tcs->push_back(osg::Vec2(quad1[i][0],quad1[i][1])/200.0); 
    322                 nrms->push_back(nrm); 
    323         } 
    324         for (i = 0; i < 4; i++) { 
    325                 coords->push_back(osg::Vec3(quad2[i][0],quad2[i][2],quad2[i][1])); 
    326                 tcs->push_back(osg::Vec2(quad2[i][0],quad2[i][1])/200.0); 
    327                 nrms->push_back(nrm); 
    328         } 
    329         for (i = 0; i < 3; i++) { 
    330                 coords->push_back(osg::Vec3(tri[i][0],tri[i][2],tri[i][1])); 
    331                 tcs->push_back(osg::Vec2(tri[i][0],tri[i][1])/200.0); 
    332                 nrms->push_back(nrm); 
    333         } 
    334         // add one large quad with multiple holes 
    335         for (i = 0; i < 4; i++) { 
    336                 coords->push_back(osg::Vec3(quad3[i][0],quad3[i][2],quad3[i][1])); 
    337                 tcs->push_back(osg::Vec2(quad3[i][0],quad3[i][1])/200.0); 
    338                 nrms->push_back(nrm); 
    339         } 
    340         { 
    341                 osg::Vec3 centre(300,0,1500); 
    342                 for (i = 0; i < 18; i++) { 
    343                         osg::Vec3 rim=centre+osg::Vec3(-cos(osg::DegreesToRadians((float)i*20.0)),0.0,sin(osg::DegreesToRadians((float)i*20.0)))*150.0; 
    344                         coords->push_back(rim); 
    345                         tcs->push_back(osg::Vec2(rim.x(),rim.z())/200.0); 
    346                         nrms->push_back(nrm); 
    347                 } 
    348         } 
    349         { 
    350                 osg::Vec3 centre(400,0,1800); 
    351                 for (i = 0; i < 18; i++) { 
    352                         osg::Vec3 rim=centre+osg::Vec3(-cos(osg::DegreesToRadians((float)i*15.0)),0.0,sin(osg::DegreesToRadians((float)i*15.0)))*250.0; 
    353                         coords->push_back(rim); 
    354                         tcs->push_back(osg::Vec2(rim.x(),rim.z())/200.0); 
    355                         nrms->push_back(nrm); 
    356                 } 
    357         } 
    358         { 
    359                 osg::Vec3 centre(600,0,1400); 
    360                 for (i = 0; i < 18; i++) { 
    361                         osg::Vec3 rim=centre+osg::Vec3(-cos(osg::DegreesToRadians((float)i*12.0)),0.0,sin(osg::DegreesToRadians((float)i*12.0)))*250.0; 
    362                         coords->push_back(rim); 
    363                         tcs->push_back(osg::Vec2(rim.x(),rim.z())/200.0); 
    364                         nrms->push_back(nrm); 
    365                 } 
    366         } 
    367         // add one large quadstrip  
    368         for (i = 0; i < 8; i++) { 
    369                 coords->push_back(osg::Vec3(quadstrip[i][0],quadstrip[i][2],quadstrip[i][1])); 
    370                 tcs->push_back(osg::Vec2(quadstrip[i][0],quadstrip[i][1])/200.0); 
    371                 nrms->push_back(nrm); 
    372         } 
    373         gtess->setVertexArray(coords); 
    374         gtess->setNormalArray(nrms); 
    375         gtess->setTexCoordArray(0,tcs); 
    376          
    377         // demonstrate that the tesselator makes textured tesselations 
    378         osg::StateSet* stateset = new osg::StateSet(); 
    379          
    380         osg::Image* image = osgDB::readImageFile("Images/osg_posz.png"); 
    381         if (image) 
    382         { 
    383                 osg::Texture2D* texture = new osg::Texture2D; 
    384                 texture->setImage(image); 
    385                 stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
    386         } 
    387         gtess->setStateSet( stateset ); 
    388          
    389         int nstart=0; 
    390         // the contours accepoted are polygons; quads & tris. Trifans can bve added later. 
    391         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,12));nstart+=12; 
    392         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,12));nstart+=12; 
    393         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,16));nstart+=16; 
    394         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,4));nstart+=4; 
    395         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,4));nstart+=4; 
    396         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,nstart,3));nstart+=3; 
    397         // A rectabngle with multiple holes 
    398         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,nstart,4));nstart+=4; 
    399         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,nstart,18));nstart+=18; 
    400         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,18));nstart+=18; 
    401         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,18));nstart+=18; 
    402         // test for quad strip 
    403         gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,nstart,8));nstart+=8; 
    404          
    405         // We need to access the tesselatable contours again to demonstrate all types of tesselation. 
    406         // I could add the Tesselator to the geometry as userdata, but here 
    407         // I use the derived tesselateDemoGeometry to hold both the drawable geode and the original contours. 
    408          
    409         gtess->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
    410         gtess->setBoundaryOnly(true); 
    411         gtess->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); // so that first change in wind type makes the commonest tesselation - ODD. 
    412          
    413         return gtess; 
     289    tesselateDemoGeometry *gtess= new tesselateDemoGeometry; 
     290    int i; 
     291    osg::Vec3Array *coords = new osg::Vec3Array; 
     292    osg::Vec3Array *nrms = new osg::Vec3Array; 
     293    osg::Vec2Array *tcs = new osg::Vec2Array; 
     294    osg::Vec3 nrm(0,-1,0); 
     295    // coordinates from red book code but shifted by 1000 & 2000 for alternate tesselatory things. 
     296    static GLdouble rects[12][3] =  
     297    { { 50.0, 50.0, 0.0 }, 
     298      { 300.0, 50.0, 0.0 },  
     299      { 300.0, 300.0, 0.0 }, 
     300      { 50.0, 300.0, 0.0 }, 
     301      { 100.0, 100.0, 0.0 }, 
     302      { 250.0, 100.0, 0.0 },  
     303      { 250.0, 250.0, 0.0 }, 
     304      { 100.0, 250.0, 0.0 }, 
     305      { 150.0, 150.0, 0.0 }, 
     306      { 200.0, 150.0, 0.0 },  
     307      { 200.0, 200.0, 0.0 }, 
     308      { 150.0, 200.0, 0.0 } }; 
     309 
     310    static GLdouble rectsMidanti[12][3] = // the centre 2 contours are traversed opposite order to outer contour. 
     311    { { 1050.0, 50.0, 0.0 }, 
     312      { 1300.0, 50.0, 0.0 },  
     313      { 1300.0, 300.0, 0.0 }, 
     314      { 1050.0, 300.0, 0.0 }, 
     315      { 1250.0, 100.0, 0.0 }, 
     316      { 1100.0, 100.0, 0.0 },  
     317      { 1100.0, 250.0, 0.0 }, 
     318      { 1250.0, 250.0, 0.0 },  
     319      { 1200.0, 150.0, 0.0 }, 
     320      { 1150.0, 150.0, 0.0 },  
     321      { 1150.0, 200.0, 0.0 }, 
     322      { 1200.0, 200.0, 0.0 } }; 
     323    static GLdouble spiral[16][3] = // shift by 1000; nb the order of vertices is reversed from that of the red book 
     324    { { 3400.0, 250.0, 0.0 }, 
     325      { 3400.0, 50.0, 0.0 },  
     326      { 3050.0, 50.0, 0.0 },   
     327      { 3050.0, 400.0, 0.0 },  
     328      { 3350.0, 400.0, 0.0 },  
     329      { 3350.0, 100.0, 0.0 },  
     330      { 3100.0, 100.0, 0.0 },  
     331      { 3100.0, 350.0, 0.0 },  
     332      { 3300.0, 350.0, 0.0 },  
     333      { 3300.0, 150.0, 0.0 },  
     334      { 3150.0, 150.0, 0.0 },  
     335      { 3150.0, 300.0, 0.0 },  
     336      { 3250.0, 300.0, 0.0 },  
     337      { 3250.0, 200.0, 0.0 },  
     338      { 3200.0, 200.0, 0.0 },  
     339      { 3200.0, 250.0, 0.0 } 
     340    }; 
     341    static GLdouble quad1[4][3] = // shift by 2000 for next 3 things 
     342    { { 2050.0, 150.0, 0.0 },  
     343      { 2350.0, 150.0, 0.0 },  
     344      { 2350.0, 200.0, 0.0 },  
     345      { 2050.0, 200.0, 0.0 } 
     346    }; 
     347    static GLdouble quad2[4][3] = 
     348    { { 2100.0, 100.0, 0.0 }, 
     349      { 2300.0, 100.0, 0.0 },  
     350      { 2300.0, 350.0, 0.0 },  
     351      { 2100.0, 350.0, 0.0 } 
     352    }; 
     353    static GLdouble tri[3][3] = 
     354    { { 2200.0, 50.0, 0.0 },  
     355      { 2250.0, 300.0, 0.0 }, 
     356      { 2150.0, 300.0, 0.0 } 
     357    }; 
     358    static GLdouble quad3[4][3] = 
     359    { { 100.0, 1100.0, 0.0 },  
     360      { 1300.0, 1100.0, 0.0 },  
     361      { 1300.0, 2350.0, 0.0 },  
     362      { 100.0, 2350.0, 0.0} 
     363    }; 
     364    static GLdouble quadstrip[8][3] = 
     365    { { 900.0, 1130.0, 0.0 }, 
     366      { 1100.0, 1130.0, 0.0 },  
     367      { 900.0, 1350.0, 0.0 }, 
     368      { 950.0, 1350.0, 0.0 },  
     369      { 900.0, 1550.0, 0.0 }, 
     370      { 1000.0, 1550.0, 0.0 }, 
     371      { 900.0, 1750.0, 0.0 }, 
     372      { 1400.0, 1750.0, 0.0 } 
     373    }; 
     374     
     375    for (i = 0; i < 12; i++) { 
     376        coords->push_back(osg::Vec3(rects[i][0],rects[i][2],rects[i][1])); 
     377        tcs->push_back(osg::Vec2(rects[i][0],rects[i][1])/200.0); 
     378        nrms->push_back(nrm); 
     379    } 
     380    for (i = 0; i < 12; i++) { 
     381        coords->push_back(osg::Vec3(rectsMidanti[i][0],rectsMidanti[i][2],rectsMidanti[i][1])); 
     382        tcs->push_back(osg::Vec2(rectsMidanti[i][0],rectsMidanti[i][1])/200.0); 
     383        nrms->push_back(nrm); 
     384    } 
     385    for (i = 0; i < 16; i++) { // and reverse spiral to make same as that of red book ch 11 
     386        coords->push_back(osg::Vec3(spiral[15-i][0],spiral[15-i][2],spiral[15-i][1])); 
     387        tcs->push_back(osg::Vec2(spiral[15-i][0],spiral[15-i][1])/200.0); 
     388        nrms->push_back(nrm); 
     389    } 
     390    for (i = 0; i < 4; i++) { 
     391        coords->push_back(osg::Vec3(quad1[i][0],quad1[i][2],quad1[i][1])); 
     392        tcs->push_back(osg::Vec2(quad1[i][0],quad1[i][1])/200.0); 
     393        nrms->push_back(nrm); 
     394    } 
     395    for (i = 0; i < 4; i++) { 
     396        coords->push_back(osg::Vec3(quad2[i][0],quad2[i][2],quad2[i][1])); 
     397        tcs->push_back(osg::Vec2(quad2[i][0],quad2[i][1])/200.0); 
     398        nrms->push_back(nrm); 
     399    } 
     400    for (i = 0; i < 3; i++) { 
     401        coords->push_back(osg::Vec3(tri[i][0],tri[i][2],tri[i][1])); 
     402        tcs->push_back(osg::Vec2(tri[i][0],tri[i][1])/200.0); 
     403        nrms->push_back(nrm); 
     404    } 
     405    // add one large quad with multiple holes 
     406    for (i = 0; i < 4; i++) { 
     407        coords->push_back(osg::Vec3(quad3[i][0],quad3[i][2],quad3[i][1])); 
     408        tcs->push_back(osg::Vec2(quad3[i][0],quad3[i][1])/200.0); 
     409        nrms->push_back(nrm); 
     410    } 
     411    { 
     412        osg::Vec3 centre(300,0,1500); 
     413        for (i = 0; i < 18; i++) { 
     414            osg::Vec3 rim=centre+osg::Vec3(-cos(osg::DegreesToRadians((float)i*20.0)),0.0,sin(osg::DegreesToRadians((float)i*20.0)))*150.0; 
     415            coords->push_back(rim); 
     416            tcs->push_back(osg::Vec2(rim.x(),rim.z())/200.0); 
     417            nrms->push_back(nrm); 
     418        } 
     419    } 
     420    { 
     421        osg::Vec3 centre(400,0,1800); 
     422        for (i = 0; i < 18; i++) { 
     423            osg::Vec3 rim=centre+osg::Vec3(-cos(osg::DegreesToRadians((float)i*15.0)),0.0,sin(osg::DegreesToRadians((float)i*15.0)))*250.0; 
     424            coords->push_back(rim); 
     425            tcs->push_back(osg::Vec2(rim.x(),rim.z())/200.0); 
     426            nrms->push_back(nrm); 
     427        } 
     428    } 
     429    { 
     430        osg::Vec3 centre(600,0,1400); 
     431        for (i = 0; i < 18; i++) { 
     432            osg::Vec3 rim=centre+osg::Vec3(-cos(osg::DegreesToRadians((float)i*12.0)),0.0,sin(osg::DegreesToRadians((float)i*12.0)))*250.0; 
     433            coords->push_back(rim); 
     434            tcs->push_back(osg::Vec2(rim.x(),rim.z())/200.0); 
     435            nrms->push_back(nrm); 
     436        } 
     437    } 
     438    // add one large quadstrip  
     439    for (i = 0; i < 8; i++) { 
     440        coords->push_back(osg::Vec3(quadstrip[i][0],quadstrip[i][2],quadstrip[i][1])); 
     441        tcs->push_back(osg::Vec2(quadstrip[i][0],quadstrip[i][1])/200.0); 
     442        nrms->push_back(nrm); 
     443    } 
     444    gtess->setVertexArray(coords); 
     445    gtess->setNormalArray(nrms); 
     446    gtess->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
     447    gtess->setTexCoordArray(0,tcs); 
     448     
     449    // demonstrate that the tesselator makes textured tesselations 
     450    osg::StateSet* stateset = new osg::StateSet(); 
     451     
     452    osg::Image* image = osgDB::readImageFile("Cubemap_snow/posz.jpg"); 
     453    if (image) 
     454    { 
     455        osg::Texture2D* texture = new osg::Texture2D; 
     456        texture->setImage(image); 
     457        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
     458    } 
     459    gtess->setStateSet( stateset ); 
     460     
     461    int nstart=0; 
     462    // the contours accepoted are polygons; quads & tris. Trifans can bve added later. 
     463    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,12));nstart+=12; 
     464    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,12));nstart+=12; 
     465    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,16));nstart+=16; 
     466    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,4));nstart+=4; 
     467    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,nstart,4));nstart+=4; 
     468    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,nstart,3));nstart+=3; 
     469    // A rectabngle with multiple holes 
     470    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,nstart,4));nstart+=4; 
     471    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,nstart,18));nstart+=18; 
     472    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,18));nstart+=18; 
     473    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,nstart,18));nstart+=18; 
     474    // test for quad strip 
     475    gtess->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,nstart,8));nstart+=8; 
     476     
     477    // We need to access the tesselatable contours again to demonstrate all types of tesselation. 
     478    // I could add the Tesselator to the geometry as userdata, but here 
     479    // I use the derived tesselateDemoGeometry to hold both the drawable geode and the original contours. 
     480     
     481    gtess->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
     482    gtess->setBoundaryOnly(true); 
     483    gtess->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); // so that first change in wind type makes the commonest tesselation - ODD. 
     484     
     485    return gtess; 
    414486} 
    415487osg::Node* createHUD() 
     
    438510        text->setPosition(position); 
    439511        text->setText("Tesselation example - no tesselation (use 'W' wireframe to visualise)"); 
    440                 text->setColor(osg::Vec4(1.0,1.0,0.8,1.0)); 
    441                 position += delta; 
     512        text->setColor(osg::Vec4(1.0,1.0,0.8,1.0)); 
     513        position += delta; 
    442514         
    443515    }     
     
    468540 
    469541osg::Group *makeTesselateExample (void) { 
    470         osg::Group *grp=new osg::Group; 
    471         osg::Geode *gd=new osg::Geode; 
    472         gd->addDrawable(makePols()); 
    473         gd->addDrawable(makePolsTwo()); 
    474         grp->addChild(gd); 
    475  
    476         grp->addChild(makeHouse()); 
    477  
    478         return grp; 
     542    osg::Group *grp=new osg::Group; 
     543    osg::Geode *gd=new osg::Geode; 
     544    gd->addDrawable(makePols()); 
     545    gd->addDrawable(makePolsTwo()); 
     546    grp->addChild(gd); 
     547 
     548    grp->addChild(makeHouse()); 
     549 
     550    return grp; 
    479551} 
    480552 
    481553class setTesselateVisitor : public osg::NodeVisitor 
    482554{ // searches a loaded model tree for tesselatable geometries. 
    483         // used with any database model which has a renderGroup (Geode) named 'tesselate' 
    484         // or you can force a type of tess with special names or a sub-class of Geode could have extra information 
    485         // of course you can use any name to detect what is to be tesselated! 
    486         // all the polygons within the specific node are deemed to be contours, so 
    487         // any tesselation can be requested. 
     555    // used with any database model which has a renderGroup (Geode) named 'tesselate' 
     556    // or you can force a type of tess with special names or a sub-class of Geode could have extra information 
     557    // of course you can use any name to detect what is to be tesselated! 
     558    // all the polygons within the specific node are deemed to be contours, so 
     559    // any tesselation can be requested. 
    488560public: 
    489          
    490         setTesselateVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { 
    491         } 
    492         virtual void apply(osg::Geode& geode) { 
    493                 if (geode.getName().compare(0,9,"tesselate")==0) { 
    494                         for(unsigned int i=0;i<geode.getNumDrawables();++i) 
    495                         { 
    496                                 osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i)); 
    497                                 if (geom) { 
    498                                         osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator(); 
    499                                         if (tscx.valid()) { 
    500                                                 tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
    501                                                 if (geode.getName()== "tesselate") { 
    502                                                         // add a tesselator so that this geom is retesselated when N is pressed 
    503                                                         tscx->setBoundaryOnly(true); 
    504                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); // so that first change in wind type makes the commonest tesselation - ODD. 
    505                                                         geom->setUserData(tscx.get()); 
    506                                                 } else if (geode.getName()== "tesselate odd") { 
    507                                                         // OR you can just apply the tesselator once only, using these different types 
    508                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // commonest tesselation - ODD. 
    509                                                         tscx->retesselatePolygons(*geom); 
    510                                                 } else if (geode.getName()== "tesselate odd bound") { 
    511                                                         tscx->setBoundaryOnly(true); 
    512                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // tesselation - ODD, only show boundary. 
    513                                                         tscx->retesselatePolygons(*geom); 
    514                                                 } else if (geode.getName()== "tesselate positive") { 
    515                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_POSITIVE); // tesselation - pos. 
    516                                                         tscx->retesselatePolygons(*geom); 
    517                                                 } else if (geode.getName()== "tesselate positive bound") { 
    518                                                         tscx->setBoundaryOnly(true); 
    519                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_POSITIVE); 
    520                                                         tscx->retesselatePolygons(*geom); 
    521                                                 } else if (geode.getName()== "tesselate negative") { 
    522                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NEGATIVE); 
    523                                                         tscx->retesselatePolygons(*geom); 
    524                                                 } else if (geode.getName()== "tesselate negative bound") { 
    525                                                         tscx->setBoundaryOnly(true); 
    526                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NEGATIVE); 
    527                                                         tscx->retesselatePolygons(*geom); 
    528                                                 } else if (geode.getName()== "tesselate nonzero") { 
    529                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NONZERO); 
    530                                                         tscx->retesselatePolygons(*geom); 
    531                                                 } else if (geode.getName()== "tesselate nonzero bound") { 
    532                                                         tscx->setBoundaryOnly(true); 
    533                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NONZERO); 
    534                                                         tscx->retesselatePolygons(*geom); 
    535                                                 } else if (geode.getName()== "tesselate geq2") { 
    536                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); 
    537                                                         tscx->retesselatePolygons(*geom); 
    538                                                 } else if (geode.getName()== "tesselate geq2 bound") { 
    539                                                         tscx->setBoundaryOnly(true); 
    540                                                         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); 
    541                                                         tscx->retesselatePolygons(*geom); 
    542                                                 } 
    543                                         } 
    544                                 } 
    545                         } 
    546                 } 
    547         }        
     561     
     562    setTesselateVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { 
     563    } 
     564    virtual void apply(osg::Geode& geode) { 
     565        if (geode.getName().compare(0,9,"tesselate")==0) { 
     566            for(unsigned int i=0;i<geode.getNumDrawables();++i) 
     567            { 
     568                osg::Geometry* geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i)); 
     569                if (geom) { 
     570                    osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator(); 
     571                    if (tscx.valid()) { 
     572                        tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
     573                        if (geode.getName()== "tesselate") { 
     574                            // add a tesselator so that this geom is retesselated when N is pressed 
     575                            tscx->setBoundaryOnly(true); 
     576                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); // so that first change in wind type makes the commonest tesselation - ODD. 
     577                            geom->setUserData(tscx.get()); 
     578                        } else if (geode.getName()== "tesselate odd") { 
     579                            // OR you can just apply the tesselator once only, using these different types 
     580                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // commonest tesselation - ODD. 
     581                            tscx->retesselatePolygons(*geom); 
     582                        } else if (geode.getName()== "tesselate odd bound") { 
     583                            tscx->setBoundaryOnly(true); 
     584                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); // tesselation - ODD, only show boundary. 
     585                            tscx->retesselatePolygons(*geom); 
     586                        } else if (geode.getName()== "tesselate positive") { 
     587                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_POSITIVE); // tesselation - pos. 
     588                            tscx->retesselatePolygons(*geom); 
     589                        } else if (geode.getName()== "tesselate positive bound") { 
     590                            tscx->setBoundaryOnly(true); 
     591                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_POSITIVE); 
     592                            tscx->retesselatePolygons(*geom); 
     593                        } else if (geode.getName()== "tesselate negative") { 
     594                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NEGATIVE); 
     595                            tscx->retesselatePolygons(*geom); 
     596                        } else if (geode.getName()== "tesselate negative bound") { 
     597                            tscx->setBoundaryOnly(true); 
     598                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NEGATIVE); 
     599                            tscx->retesselatePolygons(*geom); 
     600                        } else if (geode.getName()== "tesselate nonzero") { 
     601                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NONZERO); 
     602                            tscx->retesselatePolygons(*geom); 
     603                        } else if (geode.getName()== "tesselate nonzero bound") { 
     604                            tscx->setBoundaryOnly(true); 
     605                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NONZERO); 
     606                            tscx->retesselatePolygons(*geom); 
     607                        } else if (geode.getName()== "tesselate geq2") { 
     608                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); 
     609                            tscx->retesselatePolygons(*geom); 
     610                        } else if (geode.getName()== "tesselate geq2 bound") { 
     611                            tscx->setBoundaryOnly(true); 
     612                            tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); 
     613                            tscx->retesselatePolygons(*geom); 
     614                        } 
     615                    } 
     616                } 
     617            } 
     618        } 
     619    }     
    548620}; 
    549621 
    550622class cxTesselateVisitor : public osg::NodeVisitor 
    551623{ // special to this demo, traverses SG and finds nodes which have been tesselated 
    552         // for test/demo purposes these nodes are of type tesselateDemoGeometry 
    553         // but you could store the Tesselator as UserData or however you like. 
    554         // the tesselator holds copies of the original contours used in the tesselation 
    555         // In this visitor, I reuse the contours to make a different type of tesselation. 
     624    // for test/demo purposes these nodes are of type tesselateDemoGeometry 
     625    // but you could store the Tesselator as UserData or however you like. 
     626    // the tesselator holds copies of the original contours used in the tesselation 
     627    // In this visitor, I reuse the contours to make a different type of tesselation. 
    556628public: 
    557          
    558         cxTesselateVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { 
    559         } 
    560         virtual void apply(osg::Geode& geode) { 
    561  
    562                 for(unsigned int i=0;i<geode.getNumDrawables();++i) 
    563                 { 
    564                         tesselateDemoGeometry *geom=dynamic_cast<tesselateDemoGeometry*>(geode.getDrawable(i)); 
    565                         if (geom) { 
    566                                 if (!geom->getBoundaryOnly()) { // turn on bounds only 
    567                                         // NB this shows only the true boundary of the curves, no internal edges                                         
    568                                         geom->setBoundaryOnly(true); 
    569                                          
    570                                 } else { // change to next type of tesselation... 
    571                                         geom->setBoundaryOnly(false); 
    572                                         switch (geom->getWindingType()) { 
    573                                         case            osgUtil::Tesselator::TESS_WINDING_ODD: 
    574                                                 geom->setWindingType(osgUtil::Tesselator::TESS_WINDING_NONZERO); 
    575                                                 break; 
    576                                         case    osgUtil::Tesselator::TESS_WINDING_NONZERO: 
    577                                                 geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_POSITIVE); 
    578                                                 break; 
    579                                         case    osgUtil::Tesselator::TESS_WINDING_POSITIVE: 
    580                                                 geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_NEGATIVE); 
    581                                                 break; 
    582                                         case    osgUtil::Tesselator::TESS_WINDING_NEGATIVE: 
    583                                                 geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); 
    584                                                 break; 
    585                                         case    osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO: 
    586                                                 geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); 
    587                                                 break; 
    588                                         } 
    589                                 } 
    590                                  
    591                                 switch (geom->getWindingType()) { // a text to be added to the scene. 
    592                                 case            osgUtil::Tesselator::TESS_WINDING_ODD: 
    593                                         str="TESS_WINDING_ODD"; 
    594                                         break; 
    595                                 case    osgUtil::Tesselator::TESS_WINDING_NONZERO: 
    596                                         str="TESS_WINDING_NONZERO"; 
    597                                         break; 
    598                                 case    osgUtil::Tesselator::TESS_WINDING_POSITIVE: 
    599                                         str="TESS_WINDING_POSITIVE"; 
    600                                         break; 
    601                                 case    osgUtil::Tesselator::TESS_WINDING_NEGATIVE: 
    602                                         str="TESS_WINDING_NEGATIVE"; 
    603                                         break; 
    604                                 case    osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO: 
    605                                         str="TESS_WINDING_ABS_GEQ_TWO"; 
    606                                         break; 
    607                                 } 
    608                                 if (geom->getBoundaryOnly()) str += " Boundary"; 
    609                                  
    610                                 geom->retesselatePolygons(*geom); 
    611                         } 
    612                         osgText::Text* txt = dynamic_cast<osgText::Text*>(geode.getDrawable(i)); 
    613                         if (txt) { 
    614                                 const osg::Vec4& ct=txt->getColor(); // pick the text to be changed by its color 
    615                                 if (ct.z()<0.9) { 
    616                                         txt->setText(str.c_str()); 
    617                                 } 
    618                         } 
    619                 } 
    620                 traverse(geode); 
    621         } 
    622          
    623         std::string str; // a label for on screen display 
     629     
     630    cxTesselateVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { 
     631    } 
     632    virtual void apply(osg::Geode& geode) { 
     633 
     634        for(unsigned int i=0;i<geode.getNumDrawables();++i) 
     635        { 
     636            tesselateDemoGeometry *geom=dynamic_cast<tesselateDemoGeometry*>(geode.getDrawable(i)); 
     637            if (geom) { 
     638                if (!geom->getBoundaryOnly()) { // turn on bounds only 
     639                    // NB this shows only the true boundary of the curves, no internal edges                     
     640                    geom->setBoundaryOnly(true); 
     641                     
     642                } else { // change to next type of tesselation... 
     643                    geom->setBoundaryOnly(false); 
     644                    switch (geom->getWindingType()) { 
     645                    case         osgUtil::Tesselator::TESS_WINDING_ODD: 
     646                        geom->setWindingType(osgUtil::Tesselator::TESS_WINDING_NONZERO); 
     647                        break; 
     648                    case    osgUtil::Tesselator::TESS_WINDING_NONZERO: 
     649                        geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_POSITIVE); 
     650                        break; 
     651                    case    osgUtil::Tesselator::TESS_WINDING_POSITIVE: 
     652                        geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_NEGATIVE); 
     653                        break; 
     654                    case    osgUtil::Tesselator::TESS_WINDING_NEGATIVE: 
     655                        geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO); 
     656                        break; 
     657                    case    osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO: 
     658                        geom->setWindingType( osgUtil::Tesselator::TESS_WINDING_ODD); 
     659                        break; 
     660                    } 
     661                } 
     662                 
     663                switch (geom->getWindingType()) { // a text to be added to the scene. 
     664                case         osgUtil::Tesselator::TESS_WINDING_ODD: 
     665                    str="TESS_WINDING_ODD"; 
     666                    break; 
     667                case    osgUtil::Tesselator::TESS_WINDING_NONZERO: 
     668                    str="TESS_WINDING_NONZERO"; 
     669                    break; 
     670                case    osgUtil::Tesselator::TESS_WINDING_POSITIVE: 
     671                    str="TESS_WINDING_POSITIVE"; 
     672                    break; 
     673                case    osgUtil::Tesselator::TESS_WINDING_NEGATIVE: 
     674                    str="TESS_WINDING_NEGATIVE"; 
     675                    break; 
     676                case    osgUtil::Tesselator::TESS_WINDING_ABS_GEQ_TWO: 
     677                    str="TESS_WINDING_ABS_GEQ_TWO"; 
     678                    break; 
     679                } 
     680                if (geom->getBoundaryOnly()) str += " Boundary"; 
     681                 
     682                geom->retesselatePolygons(*geom); 
     683            } 
     684            osgText::Text* txt = dynamic_cast<osgText::Text*>(geode.getDrawable(i)); 
     685            if (txt) { 
     686                const osg::Vec4& ct=txt->getColor(); // pick the text to be changed by its color 
     687                if (ct.z()<0.9) { 
     688                    txt->setText(str.c_str()); 
     689                } 
     690            } 
     691        } 
     692        traverse(geode); 
     693    } 
     694     
     695    std::string str; // a label for on screen display 
    624696}; 
    625697 
     
    628700public: 
    629701     
    630         KeyboardEventHandler(osg::Node *nd): 
    631                 _scene(nd) {} 
     702    KeyboardEventHandler(osg::Node *nd): 
     703        _scene(nd) {} 
    632704     
    633705        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) 
     
    639711                    if (_scene && ea.getKey()=='n') 
    640712                    { 
    641                                                 // re-tesselate the scene graph.  
    642                                                 // the same contours are re-tesselated using a new method. Old contours  
    643                                                 // & tesselation type are held internally in the derived Geode class tesselateDemoGeometry. 
    644                                                 cxTesselateVisitor tsv; 
    645                                                 _scene->accept(tsv); 
     713                        // re-tesselate the scene graph.  
     714                        // the same contours are re-tesselated using a new method. Old contours  
     715                        // & tesselation type are held internally in the derived Geode class tesselateDemoGeometry. 
     716                        cxTesselateVisitor tsv; 
     717                        _scene->accept(tsv); 
    646718                       return true; 
    647719                    } 
     
    659731        } 
    660732         
    661                 osg::Node *_scene; 
     733        osg::Node *_scene; 
    662734         
    663735}; 
     
    700772    } 
    701773     
    702     if (arguments.argc()<=1) 
    703     { 
    704         arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); 
    705    ///     return 1; 
    706     } 
    707  
    708774    osg::Timer timer; 
    709775    osg::Timer_t start_tick = timer.tick(); 
     
    715781    if (!loadedModel)  
    716782    { 
    717                 loadedModel=makeTesselateExample(); 
     783        loadedModel=makeTesselateExample(); 
    718784    } else { // if there is a loaded model: 
    719                 // tesselate by searching for geode called tesselate & tesselate it 
    720                 setTesselateVisitor tsv; 
    721                 loadedModel->accept(tsv); 
    722         } 
     785        // tesselate by searching for geode called tesselate & tesselate it 
     786        setTesselateVisitor tsv; 
     787        loadedModel->accept(tsv); 
     788    } 
    723789 
    724790    // create the hud. 
    725         osg::Group *gload= dynamic_cast<osg::Group *> (loadedModel.get()); 
    726         gload->addChild(createHUD()); 
    727  
    728          
     791    osg::Group *gload= dynamic_cast<osg::Group *> (loadedModel.get()); 
     792    gload->addChild(createHUD()); 
     793 
     794     
    729795    // any option left unread are converted into errors to write out later. 
    730796    arguments.reportRemainingOptionsAsUnrecognized(); 
     
    747813    viewer.setSceneData(loadedModel.get()); 
    748814 
    749         // add event handler for keyboard 'n' to retesselate 
     815    // add event handler for keyboard 'n' to retesselate 
    750816    viewer.getEventHandlerList().push_front(new KeyboardEventHandler(loadedModel.get())); 
    751817 
    752         // create the windows and run the threads. 
     818    // create the windows and run the threads. 
    753819    viewer.realize(); 
    754820