Show
Ignore:
Timestamp:
10/27/05 11:37:38 (9 years ago)
Author:
robert
Message:

From Geoff Michel, update to osgdelaunday.

Files:
1 modified

Legend:

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

    r4611 r4621  
    3535*/ 
    3636class WallConstraint: public osgUtil::DelaunayConstraint { // forces lines to eb edge 
    37         // wall constraint - can generate a wall at the coordinates of the constraint 
     37    // wall constraint - can generate a wall at the coordinates of the constraint 
    3838public: 
    3939/** if you derive a class from DelaunayConstraint then you can create  
    4040*  a specific geometry creation routine. 
    41         */ 
    42         WallConstraint() : height(0), txxrepWall(10), txyrepWall(10)  { } 
    43          
    44         /** or create a wall around the constraint area: */ 
    45         virtual osg::Geometry * makeWallGeometry(const osg::Vec3Array *points) const; 
    46          
    47         /** for basic purposes, you can call these routines to make simple fill in geometries */ 
    48         virtual osg::DrawArrays* makeWall(void ) const { // build a wall height high around the constraint 
    49                 const osg::Vec3Array *_line= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    50                 return (new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,2*_line->size())); 
    51         } 
    52          
    53          
    54         virtual osg::Vec3Array *getWall(const osg::Vec3Array *points,const float height) const; 
    55         virtual osg::Vec2Array *getWallTexcoords(const osg::Vec3Array *points,const float height) const; 
    56         virtual osg::Vec3Array *getWallNormals(const osg::Vec3Array *points) const { 
    57                 osg::ref_ptr<osg::Vec3Array> nrms=new osg::Vec3Array; 
    58                 const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    59                 for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
    60                         const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
    61                         if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP ||  
    62                                 prset->getMode()==osg::PrimitiveSet::LINE_STRIP) { // loops and walls 
    63                                 // start with the last point on the loop 
    64                                 osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
    65                                 for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
    66                                         const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    67                                         osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
    68                                         nrm.normalize(); 
    69                                         nrms->push_back(nrm); 
    70                                         nrms->push_back(nrm); 
    71                                         prevp=curp; 
    72                                 } 
    73                                 const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
    74                                 osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
    75                                 nrm.normalize(); 
    76                                 nrms->push_back(nrm); 
    77                                 nrms->push_back(nrm); 
    78                         } 
    79                 } 
    80                 return nrms.release(); 
    81         } 
    82          
    83          
    84          
    85         // geometry creation parameters 
    86         void setWallTexrep(const float w,const float h) { txxrepWall=w;txyrepWall=h;} 
    87          
    88         /** Wall Geometry will return with this texture applied: */ 
    89         void setTexture(const char *tx) { texture=tx;} 
    90         /** fence/wall height */ 
    91         void setHeight(const float h) { height=h;} 
     41    */ 
     42    WallConstraint() : height(0), txxrepWall(10), txyrepWall(10)  { } 
     43     
     44    /** or create a wall around the constraint area: */ 
     45    virtual osg::Geometry * makeWallGeometry(void) const; 
     46     
     47    /** for basic purposes, you can call these routines to make simple fill in geometries */ 
     48    virtual osg::DrawArrays* makeWall(void ) const { // build a wall height high around the constraint 
     49        const osg::Vec3Array *_line= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     50        return (new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,2*_line->size())); 
     51    } 
     52     
     53     
     54    virtual osg::Vec3Array *getWall(const float height) const; 
     55    virtual osg::Vec2Array *getWallTexcoords(const float height) const; 
     56    virtual osg::Vec3Array *getWallNormals(void) const { 
     57        osg::ref_ptr<osg::Vec3Array> nrms=new osg::Vec3Array; 
     58        const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     59        for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
     60            const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
     61            if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP ||  
     62                prset->getMode()==osg::PrimitiveSet::LINE_STRIP) { // loops and walls 
     63                // start with the last point on the loop 
     64                osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
     65                for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
     66                    const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     67                    osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
     68                    nrm.normalize(); 
     69                    nrms->push_back(nrm); 
     70                    nrms->push_back(nrm); 
     71                    prevp=curp; 
     72                } 
     73                const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
     74                osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
     75                nrm.normalize(); 
     76                nrms->push_back(nrm); 
     77                nrms->push_back(nrm); 
     78            } 
     79        } 
     80        return nrms.release(); 
     81    } 
     82     
     83     
     84     
     85    // geometry creation parameters 
     86    void setWallTexrep(const float w,const float h) { txxrepWall=w;txyrepWall=h;} 
     87     
     88    /** Wall Geometry will return with this texture applied: */ 
     89    void setTexture(const char *tx) { texture=tx;} 
     90    /** fence/wall height */ 
     91    void setHeight(const float h) { height=h;} 
    9292protected: 
    93         float height; 
    94         std::string texture; 
    95         float txxrepWall, txyrepWall; 
     93    float height; 
     94    std::string texture; 
     95    float txxrepWall, txyrepWall; 
    9696}; 
    9797class ArealConstraint: public osgUtil::DelaunayConstraint { // forces edges of an area to fit triangles 
    98         // areal constraint - general nonuniform field, forest, lake etc. 
     98    // areal constraint - general nonuniform field, forest, lake etc. 
    9999public: 
    100100/** if you derive a class from DelaunayConstraint then you can create  
    101101*  a specific geometry creation routine. 
    102         */ 
    103         ArealConstraint() : txxrepArea(10), txyrepArea(10),txxrepWall(10), txyrepWall(10) { } 
    104          
    105         /** return a geometry that fills the constraint. 
    106         */ 
    107         virtual osg::Geometry * makeAreal( osg::Vec3Array *points); 
    108          
    109         /** or create a wall around the constraint area: */ 
    110         virtual osg::Geometry * makeWallGeometry( osg::Vec3Array *points) ; 
    111          
    112         /** for basic purposes, you can call these routines to make simple fill in geometries */ 
    113         virtual osg::DrawArrays* makeWall(void ) const; 
    114         virtual osg::Vec3Array *getWall(const osg::Vec3Array *points,const float height) const; 
    115         virtual osg::Vec2Array *getWallTexcoords(const osg::Vec3Array *points,const float height) const; 
    116         virtual osg::Vec3Array *getWallNormals(const osg::Vec3Array *points) const; 
    117         /** Canopies are the same triangles as the terrain but offset by height above 
    118         * (height might be 0). */ 
    119         virtual osg::DrawArrays* makeCanopy(void ) const; 
    120         virtual osg::Vec3Array *getCanopy(const osg::Vec3Array *points,const float height) const; 
    121         virtual osg::Vec2Array *getCanopyTexcoords(const osg::Vec3Array *points) const; 
    122         virtual osg::Vec3Array *getCanopyNormals(const osg::Vec3Array *points) const; 
    123          
    124         // geometry creation parameters 
    125         void setTexrep(const float w,const float h) { txxrepArea=w;txyrepArea=h;} 
    126         void setWallTexrep(const float w,const float h) { txxrepWall=w;txyrepWall=h;} 
    127         /** Geometry will return with this texture applied: */ 
    128         void setWallTexture(const char *tx) { walltexture=tx;} 
    129         /** Geometry will return with this texture applied: */ 
    130         void setTexture(const char *tx) { texture=tx;} 
    131         /** fence/wall height */ 
    132         void setHeight(const float h) { height=h;} 
    133         std::string walltexture; 
     102    */ 
     103    ArealConstraint() : txxrepArea(10), txyrepArea(10),txxrepWall(10), txyrepWall(10) { } 
     104     
     105    /** return a geometry that fills the constraint. 
     106    */ 
     107    virtual osg::Geometry * makeAreal( osg::Vec3Array *points); 
     108     
     109    /** or create a wall around the constraint area: */ 
     110    virtual osg::Geometry * makeWallGeometry( osg::Vec3Array *points) ; 
     111     
     112    /** for basic purposes, you can call these routines to make simple fill in geometries */ 
     113    virtual osg::DrawArrays* makeWall(void ) const; 
     114    virtual osg::Vec3Array *getWall(const float height) const; 
     115    virtual osg::Vec2Array *getWallTexcoords(const float height) const; 
     116    virtual osg::Vec3Array *getWallNormals(void) const; 
     117    /** Canopies are the same triangles as the terrain but offset by height above 
     118    * (height might be 0). */ 
     119    virtual osg::DrawArrays* makeCanopy(void ) const; 
     120    virtual osg::Vec3Array *getCanopy(const osg::Vec3Array *points,const float height) const; 
     121    virtual osg::Vec2Array *getCanopyTexcoords(const osg::Vec3Array *points) const; 
     122    virtual osg::Vec3Array *getCanopyNormals(const osg::Vec3Array *points) const; 
     123     
     124    // geometry creation parameters 
     125    void setTexrep(const float w,const float h) { txxrepArea=w;txyrepArea=h;} 
     126    void setWallTexrep(const float w,const float h) { txxrepWall=w;txyrepWall=h;} 
     127    /** Geometry will return with this texture applied: */ 
     128    void setWallTexture(const char *tx) { walltexture=tx;} 
     129    /** Geometry will return with this texture applied: */ 
     130    void setTexture(const char *tx) { texture=tx;} 
     131    /** fence/wall height */ 
     132    void setHeight(const float h) { height=h;} 
     133    std::string walltexture; 
    134134protected: 
    135         float height; 
    136         std::string texture; 
    137         float txxrepArea, txyrepArea; 
    138         float txxrepWall, txyrepWall; 
     135    float height; 
     136    std::string texture; 
     137    float txxrepArea, txyrepArea; 
     138    float txxrepWall, txyrepWall; 
    139139}; 
    140140 
     
    142142/** forces edges of a "road" to fit triangles 
    143143*  if 2 roads cross, then the overlap will be replaced by a 'cross road' 
    144         *  and the roads built up to the cross roads with a texture along its length. */ 
     144    *  and the roads built up to the cross roads with a texture along its length. */ 
    145145public: 
    146         LinearConstraint() : DelaunayConstraint(), txxrepAlong(10), txyrepAcross(10), width(2) { } 
    147          
    148         /** geometry creation parameters */ 
    149         /* Width of linear feature (eg road, railway) */ 
    150         void setWidth(const float w) { width=w;} 
    151          
    152         /** Texture repeat distance across linear (often equal to width) and along its length */ 
    153         virtual void setTexrep(const float w,const float h) { txyrepAcross=h;txxrepAlong=w; } 
    154          
    155         /** generate constant width around line - creates the area to be cut into the terrain. */ 
    156         virtual void setVertices( osg::Vec3Array *lp, const float width); 
    157          
    158         /** return a geometry that fills the constraint. 
    159         */ 
    160         virtual osg::Geometry *makeGeometry(const osg::Vec3Array *points) ; 
    161          
    162         /** return normals array - flat shaded */ 
    163         osg::Vec3Array* getNormals(const osg::Vec3Array *points); 
    164          
    165         /** Roads apply a texture proportional to length along the road line. */ 
    166         virtual osg::DrawArrays* makeRoad( ) const; 
    167         virtual osg::Vec3Array *getRoadVertices(const osg::Vec3Array *points) const; 
    168         virtual osg::Vec2Array *getRoadTexcoords(const osg::Vec3Array *points) ; 
    169          
    170         virtual osg::Vec3Array *getRoadNormals(const osg::Vec3Array *points) const; 
    171         /** Geometry will return with this texture applied: */ 
    172         void setTexture(const char *tx) { texture=tx;} 
    173          
     146    LinearConstraint() : DelaunayConstraint(), txxrepAlong(10), txyrepAcross(10), width(2) { } 
     147     
     148    /** geometry creation parameters */ 
     149    /* Width of linear feature (eg road, railway) */ 
     150    void setWidth(const float w) { width=w;} 
     151     
     152    /** Texture repeat distance across linear (often equal to width) and along its length */ 
     153    virtual void setTexrep(const float w,const float h) { txyrepAcross=h;txxrepAlong=w; } 
     154     
     155    /** generate constant width around line - creates the area to be cut into the terrain. */ 
     156    virtual void setVertices( osg::Vec3Array *lp, const float width); 
     157     
     158    /** return a geometry that fills the constraint. 
     159    */ 
     160    virtual osg::Geometry *makeGeometry(const osg::Vec3Array *points) ; 
     161     
     162    /** return normals array - flat shaded */ 
     163    osg::Vec3Array* getNormals(const osg::Vec3Array *points); 
     164     
     165    /** Roads apply a texture proportional to length along the road line. */ 
     166    virtual osg::DrawArrays* makeRoad( ) const; 
     167    virtual osg::Vec3Array *getRoadVertices() const; 
     168    virtual osg::Vec2Array *getRoadTexcoords(const osg::Vec3Array *points) ; 
     169     
     170    virtual osg::Vec3Array *getRoadNormals(const osg::Vec3Array *points) const; 
     171    /** Geometry will return with this texture applied: */ 
     172    void setTexture(const char *tx) { texture=tx;} 
     173     
    174174protected: 
    175         osg::ref_ptr<osg::Vec2Array> _tcoords; 
    176         osg::ref_ptr<osg::Vec3Array> _edgecoords; 
    177         float txxrepAlong, txyrepAcross; 
    178         std::string texture; 
    179         float width; // width of a linear feature 
    180         osg::ref_ptr<osg::Vec3Array> _midline; // defines the midline of a road, rail etc. 
     175    osg::ref_ptr<osg::Vec2Array> _tcoords; 
     176    osg::ref_ptr<osg::Vec3Array> _edgecoords; 
     177    float txxrepAlong, txyrepAcross; 
     178    std::string texture; 
     179    float width; // width of a linear feature 
     180    osg::ref_ptr<osg::Vec3Array> _midline; // defines the midline of a road, rail etc. 
    181181}; 
    182182 
     
    185185class pyramid : public osgUtil::DelaunayConstraint { 
    186186/** sample user constriant - creates hole in terrain to fit base of pyramid, and 
    187         *  geometry of an Egyptian pyramid to fit the hole. */ 
     187    *  geometry of an Egyptian pyramid to fit the hole. */ 
    188188public: 
    189         pyramid() : _side(100.) {} 
    190          
    191         void setpos(const osg::Vec3 p, const float size) { _pos=p;_side=size;} 
    192          
    193         virtual osg::Geometry * makeGeometry(const osg::Vec3Array *points) const 
     189    pyramid() : _side(100.) {} 
     190     
     191    void setpos(const osg::Vec3 p, const float size) { _pos=p;_side=size;} 
     192     
     193    virtual osg::Geometry * makeGeometry(void) const 
    194194        { 
    195                 // create pyramid geometry. Centre plus points around base 
    196                 const osg::Vec3Array *_line= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    197                 osg::Geometry *gm=new osg::Geometry; 
    198                 osg::Vec3Array *pts=new osg::Vec3Array; 
    199                 osg::Vec3Array *norms=new osg::Vec3Array; 
    200                 osg::Vec2Array *tcoords=new osg::Vec2Array; 
    201                 int ip; 
    202                  
    203                 pts->push_back(_pos+osg::Vec3(0,0,_side)*0.5); 
    204                 for (ip=0; ip<4; ip++) { 
    205                         pts->push_back((*_line)[ip]); 
    206                 } 
    207                 for (ip=1; ip<5; ip++) { 
    208                         osg::Vec3 nrm=((*pts)[ip]-(*pts)[0])^((*pts)[ip==4?0:ip+1]-(*pts)[ip]); 
    209                         nrm.normalize(  ); 
    210                         norms->push_back(nrm); 
    211                 } 
    212                  
    213                 gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
    214                 gm->setVertexArray(pts); 
    215                 osg::StateSet *dstate=   gm->getOrCreateStateSet(  ); 
    216                 dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
    217                  
    218                 osg::Image* image = osgDB::readImageFile("stoneWall.jpg"); 
    219                 if (image) 
    220                 { 
    221                         osg::Texture2D* txt = new osg::Texture2D; 
    222                         txt->setImage(image); 
    223                         txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
    224                         txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
    225                         dstate->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
    226                 } 
    227                 gm->setNormalArray(norms); 
    228                 ////            gm->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,0,6)); 
    229                 osg::DrawElementsUInt *dui=new osg::DrawElementsUInt(GL_TRIANGLES); 
    230                 for (ip=0; ip<4; ip++) { 
    231                         dui->push_back(0); 
    232                         dui->push_back(ip+1); 
    233                         dui->push_back(ip==3?1:ip+2); 
    234                 } 
    235                 tcoords->push_back(osg::Vec2(2,4)); 
    236                 tcoords->push_back(osg::Vec2(0,0)); 
    237                 tcoords->push_back(osg::Vec2(4,0)); 
    238                 tcoords->push_back(osg::Vec2(0,0)); 
    239                 tcoords->push_back(osg::Vec2(4,0)); 
    240                 gm->setTexCoordArray(0,tcoords); 
    241                 gm->addPrimitiveSet(dui); 
    242                 return gm; 
    243         } 
    244         virtual void calcVertices( void) { // must have a position first 
    245                 osg::Vec3Array *edges=new osg::Vec3Array; 
    246                 osg::Vec3 valong; 
    247                 edges->push_back(_pos+osg::Vec3(0.5,0.5,0)*_side); 
    248                 edges->push_back(_pos+osg::Vec3(-0.5,0.5,0)*_side); 
    249                 edges->push_back(_pos+osg::Vec3(-0.5,-0.5,0)*_side); 
    250                 edges->push_back(_pos+osg::Vec3(0.5,-0.5,0)*_side); 
    251                 setVertexArray(edges); 
    252         } 
     195        // create pyramid geometry. Centre plus points around base 
     196        const osg::Vec3Array *_line= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     197        osg::Geometry *gm=new osg::Geometry; 
     198        osg::Vec3Array *pts=new osg::Vec3Array; 
     199        osg::Vec3Array *norms=new osg::Vec3Array; 
     200        osg::Vec2Array *tcoords=new osg::Vec2Array; 
     201        int ip; 
     202         
     203        pts->push_back(_pos+osg::Vec3(0,0,_side)*0.5); 
     204        for (ip=0; ip<4; ip++) { 
     205            pts->push_back((*_line)[ip]); 
     206        } 
     207        for (ip=1; ip<5; ip++) { 
     208            osg::Vec3 nrm=((*pts)[ip]-(*pts)[0])^((*pts)[ip==4?0:ip+1]-(*pts)[ip]); 
     209            nrm.normalize(  ); 
     210            norms->push_back(nrm); 
     211        } 
     212         
     213        gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
     214        gm->setVertexArray(pts); 
     215        osg::StateSet *dstate=   gm->getOrCreateStateSet(  ); 
     216        dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
     217         
     218        osg::Image* image = osgDB::readImageFile("stoneWall.jpg"); 
     219        if (image) 
     220        { 
     221            osg::Texture2D* txt = new osg::Texture2D; 
     222            txt->setImage(image); 
     223            txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
     224            txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
     225            dstate->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
     226        } 
     227        gm->setNormalArray(norms); 
     228        ////        gm->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,0,6)); 
     229        osg::DrawElementsUInt *dui=new osg::DrawElementsUInt(GL_TRIANGLES); 
     230        for (ip=0; ip<4; ip++) { 
     231            dui->push_back(0); 
     232            dui->push_back(ip+1); 
     233            dui->push_back(ip==3?1:ip+2); 
     234        } 
     235        tcoords->push_back(osg::Vec2(2,4)); 
     236        tcoords->push_back(osg::Vec2(0,0)); 
     237        tcoords->push_back(osg::Vec2(4,0)); 
     238        tcoords->push_back(osg::Vec2(0,0)); 
     239        tcoords->push_back(osg::Vec2(4,0)); 
     240        gm->setTexCoordArray(0,tcoords); 
     241        gm->addPrimitiveSet(dui); 
     242        return gm; 
     243    } 
     244    virtual void calcVertices( void) { // must have a position first 
     245        osg::Vec3Array *edges=new osg::Vec3Array; 
     246        osg::Vec3 valong; 
     247        edges->push_back(_pos+osg::Vec3(0.5,0.5,0)*_side); 
     248        edges->push_back(_pos+osg::Vec3(-0.5,0.5,0)*_side); 
     249        edges->push_back(_pos+osg::Vec3(-0.5,-0.5,0)*_side); 
     250        edges->push_back(_pos+osg::Vec3(0.5,-0.5,0)*_side); 
     251        setVertexArray(edges); 
     252    } 
    253253private: 
    254         osg::Vec3 _pos; // where the pyramid is 
    255         float _side ; // length of side 
     254    osg::Vec3 _pos; // where the pyramid is 
     255    float _side ; // length of side 
    256256}; 
    257257 
    258258float getheight(const float x, const float y) 
    259259{ // returns the x,y,height of terrain 
    260         return 150*sin(x*.0020)*cos(y*.0020); 
     260    return 150*sin(x*.0020)*cos(y*.0020); 
    261261} 
    262262osg::Vec3d getpt(const int np) 
    263263{ // returns the x,y,height of terrain up to maxp^2 points 
    264         static int maxp =40; 
    265         int i=np/maxp; 
    266         int j=np%maxp; 
    267         // make the random scale 0.00 if you want an equispaced XY grid. 
    268         float x=3000.0/(maxp-1)*i+0.00052*rand(); 
    269         float y=3000.0/(maxp-1)*j+0.0005*rand(); 
    270         float z=getheight(x,y); 
    271         if (np>=maxp*maxp) z=-1.e32; 
    272         return osg::Vec3d(x,y,z); 
     264    static int maxp =40; 
     265    int i=np/maxp; 
     266    int j=np%maxp; 
     267    // make the random scale 0.00 if you want an equispaced XY grid. 
     268    float x=3000.0/(maxp-1)*i+0.00052*rand(); 
     269    float y=3000.0/(maxp-1)*j+0.0005*rand(); 
     270    float z=getheight(x,y); 
     271    if (np>=maxp*maxp) z=-1.e32; 
     272    return osg::Vec3d(x,y,z); 
    273273} 
    274274osg::Node* createHUD(const int ndcs,std::string what) 
     
    277277     
    278278    std::string timesFont("fonts/arial.ttf"); 
    279          
     279     
    280280    // turn lighting off for the text and disable depth test to ensure its always ontop. 
    281281    osg::StateSet* stateset = geode->getOrCreateStateSet(); 
    282282    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 
    283          
     283     
    284284    // Disable depth test, and make sure that the hud is drawn after everything  
    285285    // else so that it always appears ontop. 
    286286    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); 
    287287    stateset->setRenderBinDetails(11,"RenderBin"); 
    288          
     288     
    289289    osg::Vec3 position(50.0f,900.0f,0.0f); 
    290290    osg::Vec3 delta(0.0f,-35.0f,0.0f); 
    291          
     291     
    292292    { 
    293293        osgText::Text* text = new  osgText::Text; 
    294294        geode->addDrawable( text ); 
    295                 std::ostringstream cue; 
    296                 cue<<"Delaunay triangulation with constraints level "<<ndcs <<"\n"<< what; 
    297                  
     295        std::ostringstream cue; 
     296        cue<<"Delaunay triangulation with constraints level "<<ndcs <<"\n"<< what; 
     297         
    298298        text->setFont(timesFont); 
    299299        text->setPosition(position); 
     
    302302        position += delta*(ndcs+2); 
    303303         
    304                 text = new  osgText::Text; 
     304        text = new  osgText::Text; 
    305305        geode->addDrawable( text ); 
    306                  
     306         
    307307        text->setFont(timesFont); 
    308308        text->setPosition(position); 
     
    315315        osgText::Text* text = new  osgText::Text; 
    316316        geode->addDrawable( text ); 
    317                  
     317         
    318318        text->setFont(timesFont); 
    319319        text->setPosition(position); 
     
    321321         
    322322    }     
    323          
     323     
    324324    // create the hud. 
    325325    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform; 
     
    327327    modelview_abs->setMatrix(osg::Matrix::identity()); 
    328328    modelview_abs->addChild(geode); 
    329          
     329     
    330330    osg::Projection* projection = new osg::Projection; 
    331331    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); 
    332332    projection->addChild(modelview_abs); 
    333          
     333     
    334334    return projection; 
    335          
     335     
    336336} 
    337337osg::Group *makedelaunay(const int ndcs) 
    338338{ // create a terrain tile. This is just an example! 
    339         // ndcs is the number of delaunay constraints to be applied 
    340         osg::ref_ptr<osg::Group> grp=new osg::Group; 
    341         osg::ref_ptr<osg::Geode> geode=new osg::Geode; 
    342         osg::ref_ptr<osgUtil::DelaunayTriangulator> trig=new osgUtil::DelaunayTriangulator(); 
    343         osg::StateSet *stateset=geode->getOrCreateStateSet(); 
    344          
    345         osg::Vec3Array *points=new osg::Vec3Array; 
    346          
    347         osg::Image* image = osgDB::readImageFile("Lands-Flowers-Small_Purple.png"); 
    348         if (image) 
    349         { 
    350                 osg::Texture2D* texture = new osg::Texture2D; 
    351                 texture->setImage(image); 
    352                 texture->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
    353                 texture->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
    354                 stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
    355         } 
    356          
    357         geode->setStateSet( stateset ); 
    358         unsigned int i; 
    359          
    360         int eod=0; 
    361         while (eod>=0) { 
    362                 osg::Vec3d pos=getpt(eod); 
    363                 if (pos.z()>-10000) { 
    364                         points->push_back(pos); 
    365                         eod++; 
    366                 } else { 
    367                         eod=-9999; 
    368                 } 
    369         } 
    370         std::vector < pyramid* > pyrlist; 
    371         osg::ref_ptr<WallConstraint> wc; // This example does not remove the interior 
    372         osg::ref_ptr<ArealConstraint> dc2; 
    373         osg::ref_ptr<ArealConstraint> forest; 
    374         osg::ref_ptr<LinearConstraint> dc3; 
    375         osg::ref_ptr<LinearConstraint> dc6; 
    376         osg::ref_ptr<LinearConstraint> dc6a; 
    377         osg::ref_ptr<LinearConstraint> dc8; 
    378         osg::ref_ptr<LinearConstraint> forestroad; 
    379         osg::ref_ptr<LinearConstraint> forestroad2; 
    380         osg::ref_ptr<LinearConstraint> forestroad3; 
    381         osg::ref_ptr<osgUtil::DelaunayConstraint> dc; 
    382         std::ostringstream what; 
    383         if (1==1) { // add a simple constraint of few points 
    384                 osg::ref_ptr<osgUtil::DelaunayConstraint> dc=new osgUtil::DelaunayConstraint; 
    385                 osg::Vec3Array *bounds=new osg::Vec3Array; 
    386                 unsigned int nmax=4; 
    387                 for (i=0 ; i<nmax; i++) { 
    388                         float x=910.0+800.0*(i)/(float)nmax,y=810.0+6000*(i-1)*(i-1)/(float)(nmax*nmax); 
    389                         bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
    390                 } 
    391                 dc->setVertexArray(bounds); 
    392                 dc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,nmax) ); 
    393                  
    394                 trig->addInputConstraint(dc.get()); 
    395                 what << nmax << " point simple constraint\n"; 
    396         } 
    397         if (ndcs>0) { // add 5 pyramids 
    398                 for (unsigned int ipy=0; ipy<5/*5*/; ipy++) { 
    399                         osg::ref_ptr<pyramid> pyr=new pyramid; 
    400                         float x=2210+ipy*120, y=1120+ipy*220; 
    401                         pyr->setpos(osg::Vec3(x,y,getheight(x,y)),125.0+10*ipy); 
    402                         pyr->calcVertices(); // make vertices 
    403                         pyr->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,4) ); 
    404                         trig->addInputConstraint(pyr.get()); 
    405                         pyrlist.push_back(pyr.get()); 
    406                 } 
    407                 what << 5 << " pyramids\n"; 
    408                 if (ndcs>1) { 
    409                         // add a simple constraint feature - this can cut holes in the terrain or just leave the triangles 
    410                         // with edges forced to the constraint. 
    411                         dc=new osgUtil::DelaunayConstraint; 
    412                         osg::Vec3Array *bounds=new osg::Vec3Array; 
    413                         for (i=0 ; i<12; i++) { 
    414                                 float x=610.0+420*sin(i/3.0),y=610.0+420*cos(i/3.0); 
    415                                 bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
    416                         } 
    417                         dc->setVertexArray(bounds); 
    418                         dc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,12) ); 
    419                          
    420                         trig->addInputConstraint(dc.get()); 
    421                         what << 12 << " point closed loop"; 
    422                          
    423                         if (ndcs>2) { 
    424                                 wc=new WallConstraint; // This example does not remove the interior 
    425                                 // eg to force terrain edges that are on ridges in the terrain etc. 
    426                                 // use wireframe to see the constrained edges. 
    427                                 // NB this is not necessarily a closed loop of edges. 
    428                                 // we do however build a wall at the coordinates. 
    429                                 bounds=new osg::Vec3Array; 
    430                                 for (i=0 ; i<5; i++) { 
    431                                         float x=1610.0+420*sin(i/1.0),y=1610.0+420*cos(i/1.0); 
    432                                         bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
    433                                 } 
    434                                 wc->setVertexArray(bounds); 
    435                                 wc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,5) ); 
    436                                 wc->setHeight(12.0); 
    437                                 trig->addInputConstraint(wc.get()); 
    438                                 what << " with interior removed\n"; 
    439                                 what << 5 << " point wall derived constraint\n"; 
    440                                  
    441                                 if (ndcs>3) { 
    442                                         // add a removed area and replace it with a different texture 
    443                                         dc2=new ArealConstraint; 
    444                                         bounds=new osg::Vec3Array; 
    445                                         for (i=0 ; i<18; i++) { 
    446                                                 float x=1610.0+420*sin(i/3.0),y=610.0+220*cos(i/3.0); 
    447                                                 bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
    448                                         } 
    449                                         dc2->setVertexArray(bounds); 
    450                                         dc2->setTexrep(100,100); // texture is repeated at this frequency 
    451                                         dc2->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,18) ); 
    452                                         trig->addInputConstraint(dc2.get()); 
    453                                         what << 18 << " point area replaced\n"; 
    454                                          
    455                                         if (ndcs>4) { 
    456                                                 dc3=new LinearConstraint; 
    457                                                 // a linear feature or 'road' 
    458                                                 osg::Vec3Array *verts=new osg::Vec3Array; 
    459                                                 for (i=0 ; i<32; i++) { 
    460                                                         float x=610.0+50*i+90*sin(i/5.0),y=1110.0+90*cos(i/5.0); 
    461                                                         verts->push_back(osg::Vec3(x,y,getheight(x,y))); 
    462                                                 } 
    463                                                 dc3->setVertices(verts,9.5); // width of road 
    464                                                 for (osg::Vec3Array::iterator vit=points->begin(); vit!=points->end(); ) { 
    465                                                         if (dc3->contains(*vit)) { 
    466                                                                 vit=points->erase(vit); 
    467                                                         } else { 
    468                                                                 vit++; 
    469                                                         } 
    470                                                 } 
    471                                                 trig->addInputConstraint(dc3.get()); 
    472                                                 what << 32 << " point road constraint\n"; 
    473                                                 if (ndcs>5) { 
    474                                                         // add a removed area and replace it with a 'forest' with textured roof and walls 
    475                                                         forest=new ArealConstraint; 
    476                                                         bounds=new osg::Vec3Array; 
    477                                                         for (i=0 ; i<12; i++) { 
    478                                                                 float x=610.0+420*sin(i/2.0),y=1810.0+420*cos(i/2.0); 
    479                                                                 bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
    480                                                         } 
    481                                                         forest->setVertexArray(bounds); 
    482                                                         forest->setHeight(50); 
    483                                                         forest->setWallTexrep(100,50); 
    484                                                         forest->setTexrep(100,100); // texture is repeated at this frequency 
    485                                                         forest->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,12) ); 
    486                                                         if (ndcs==6) trig->addInputConstraint(forest.get()); 
    487                                                         what << 12 << " point forest constraint\n"; 
    488                                                          
    489                                                         if (ndcs>6) { // add roads that intersect forest 
    490                                                                 osg::ref_ptr<osgUtil::DelaunayConstraint> forestplus=new osgUtil::DelaunayConstraint; 
    491                                                                 forestroad=new LinearConstraint; 
    492                                                                 verts=new osg::Vec3Array; 
    493                                                                 for (i=0 ; i<12; i++) { 
    494                                                                         int ip=(i-6)*(i-6); 
    495                                                                         float xp=410.0+20.0*ip; 
    496                                                                         float y=1210.0+150*i; 
    497                                                                         verts->push_back(osg::Vec3(xp,y,getheight(xp,y))); 
    498                                                                 } 
    499                                                                 forestroad->setVertices(verts,22); // add road 
    500                                                                 forestplus->merge(forestroad.get()); 
    501                                                                 forestroad2=new LinearConstraint; 
    502                                                                 verts=new osg::Vec3Array; 
    503                                                                 for (i=0 ; i<12; i++) { 
    504                                                                         int ip=(i-6)*(i-6); 
    505                                                                         float xp=810.0-10.0*ip; 
    506                                                                         float y=1010.0+150*i; 
    507                                                                         verts->push_back(osg::Vec3(xp,y,getheight(xp,y))); 
    508                                                                 } 
    509                                                                 forestroad2->setVertices(verts,22); // add road 
    510                                                                 forestplus->merge(forestroad2.get()); 
    511                                                                 forestroad3=new LinearConstraint; 
    512                                                                 verts=new osg::Vec3Array; 
    513                                                                 for (i=0 ; i<6; i++) { 
    514                                                                         int ip=(i-6)*(i-6); 
    515                                                                         float xp=210.0+140.0*i+ip*10.0; 
    516                                                                         float y=1510.0+150*i; 
    517                                                                         verts->push_back(osg::Vec3(xp,y,getheight(xp,y))); 
    518                                                                 } 
    519                                                                 forestroad3->setVertices(verts,22); // add road 
    520                                                                 forestplus->merge(forestroad3.get()); 
    521                                                                 forestplus->merge(forest.get()); 
    522                                                                 forestplus->handleOverlaps(); 
    523                                                                 for (osg::Vec3Array::iterator vit=points->begin(); vit!=points->end(); ) { 
    524                                                                         if (forestroad->contains(*vit)) { 
    525                                                                                 vit=points->erase(vit); 
    526                                                                         } else if (forestroad2->contains(*vit)) { 
    527                                                                                 vit=points->erase(vit); 
    528                                                                         } else if (forestroad3->contains(*vit)) { 
    529                                                                                 vit=points->erase(vit); 
    530                                                                         } else { 
    531                                                                                 vit++; 
    532                                                                         } 
    533                                                                 } 
    534                                                                 trig->addInputConstraint(forestplus.get()); 
    535                                                                 what << " roads intersect forest constraint\n"; 
    536                                                                 if (ndcs>7) { 
    537                                                                         // this option adds a more complex DC 
    538                                                                         // made of several (ok 2 - extend your own way) overlapping DC's 
    539                                                                         osg::ref_ptr<osgUtil::DelaunayConstraint> dcoverlap=new osgUtil::DelaunayConstraint; 
    540                                                                         float x=1200; float y=1900; 
    541                                                                         { 
    542                                                                                 verts=new osg::Vec3Array; 
    543                                                                                 dc6=new LinearConstraint; 
    544                                                                                 verts->push_back(osg::Vec3(x-180,y,getheight(x-180,y))); 
    545                                                                                 verts->push_back(osg::Vec3(x+180,y,getheight(x+180,y))); 
    546                                                                                 dc6->setVertices(verts,22); // width of road 
    547                                                                                 dcoverlap->merge(dc6.get()); 
    548                                                                         } 
    549                                                                         { 
    550                                                                                 dc6a= new LinearConstraint; 
    551                                                                                 verts=new osg::Vec3Array; 
    552                                                                                 verts->push_back(osg::Vec3(x,y-180,getheight(x,y-180))); 
    553                                                                                 verts->push_back(osg::Vec3(x-20,y,getheight(x,y))); 
    554                                                                                 verts->push_back(osg::Vec3(x,y+180,getheight(x,y+180))); 
    555                                                                                 dc6a->setVertices(verts,22); // width of road 
    556                                                                                 dcoverlap->merge(dc6a.get()); 
    557                                                                         } 
    558                                                                         what << "2 intersecting roads, with added points\n"; 
    559                                                                         if (ndcs>9) { 
    560                                                                                 // add yet more roads 
    561                                                                                 dc8= new LinearConstraint; 
    562                                                                                 verts=new osg::Vec3Array; 
    563                                                                                 float rad=60.0; 
    564                                                                                 for (float theta=0; theta<4*osg::PI; theta+=0.1*osg::PI) { 
    565                                                                                         float xp=x+rad*cos(theta), yp=y+rad*sin(theta); 
    566                                                                                         verts->push_back(osg::Vec3(xp,yp,getheight(xp,yp))); 
    567                                                                                         rad+=2.5; 
    568                                                                                 } 
    569                                                                                 dc8->setVertices(verts,16); // width of road 
    570                                                                                 dcoverlap->merge(dc8.get()); 
    571                                                                                 what << "Spiral road crosses several other constraints."; 
    572                                                                         } 
    573                                                                         dcoverlap->handleOverlaps(); 
    574                                                                         if (ndcs>8) { 
    575                                                                                 // remove vertices cleans up the texturing at the intersection. 
    576                                                                                 dcoverlap->removeVerticesInside(dc6.get()); 
    577                                                                                 dcoverlap->removeVerticesInside(dc6a.get()); 
    578                                                                                 if (dc8.valid()) dcoverlap->removeVerticesInside(dc8.get()); 
    579                                                                                 what << "    remove internal vertices to improve texturing."; 
    580                                                                         } 
    581                                                                         for (osg::Vec3Array::iterator vit=points->begin(); vit!=points->end(); ) { 
    582                                                                                 if (dcoverlap->contains(*vit)) { 
    583                                                                                         vit=points->erase(vit); 
    584                                                                                 } else { 
    585                                                                                         vit++; 
    586                                                                                 } 
    587                                                                         } 
    588                                                                         trig->addInputConstraint(dcoverlap.get()); 
    589                                                                 } 
    590                                                         } 
    591                                                 } 
    592                                         } 
    593                                 } 
    594                         } 
    595                 } 
    596         } // ndcs>0 
    597         trig->setInputPointArray(points); 
    598          
    599         /** NB you need to supply a vec3 array for the triangulator to calculate normals into */ 
    600         osg::Vec3Array *norms=new osg::Vec3Array; 
    601         trig->setOutputNormalArray(norms); 
    602          
    603         trig->triangulate(); 
    604         osg::notify(osg::WARN) << " End of trig\n " <<std::endl; 
    605          
    606         // Calculate the texture coordinates after triangulation as  
    607         //the points may get disordered by the triangulate function 
    608         osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; 
    609         gm->setVertexArray(points); // points may have been modified in order by triangulation. 
    610         /** calculate texture coords for terrain points */ 
    611         if (image) { 
    612                 float repeat=150.0, ry=150.0; // how often to repeat texture 
    613                 osg::Vec2Array *tcoords=new osg::Vec2Array; 
    614                 for (osg::Vec3Array::iterator itr=points->begin(); itr!=points->end(); itr++) { 
    615                         osg::Vec2 tcatxy((*itr).x()/repeat,(*itr).y()/ry); 
    616                         tcoords->push_back(tcatxy); 
    617                 } 
    618                 gm->setTexCoordArray(0,tcoords); 
    619         } 
    620         gm->addPrimitiveSet(trig->getTriangles()); 
    621         gm->setNormalArray(trig->getOutputNormalArray()); 
    622         gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
    623         geode->addDrawable(gm.get()); 
    624         if (ndcs>0) { 
    625                 for ( std::vector < pyramid* >::iterator itr=pyrlist.begin(); itr!=pyrlist.end(); itr++) { 
    626                         trig->removeInternalTriangles(*itr); 
    627                         geode->addDrawable((*itr)->makeGeometry(points)); // this fills the holes of each pyramid with geometry 
    628                 } 
    629                  
    630                 if (ndcs>2) { 
    631                         trig->removeInternalTriangles(dc.get()); 
    632                          
    633                         wc->setTexture("Brick-Norman-Brown.TGA"); // wall looks like brick 
    634                         geode->addDrawable(wc->makeWallGeometry(points)); // this creates wall at wc drawarrays 
    635                         if (ndcs>3) { 
    636                                 trig->removeInternalTriangles(dc2.get()); 
    637                                 osg::ref_ptr<osg::Vec3Array> arpts=dc2->getPoints(points); 
    638                                 dc2->setTexture("Lands-Needles_2.png"); 
    639                                 geode->addDrawable(dc2->makeAreal(arpts.get())); // this creates fill in geometry 
    640                                  
    641                                 if (ndcs>4) { // a simple "road" 
    642                                         trig->removeInternalTriangles(dc3.get()); 
    643                                         dc3->setTexture ("road.png"); 
    644                                         dc3->setTexrep(40,9.5); // texture is repeated at this frequency 
    645                                         geode->addDrawable(dc3->makeGeometry(points)); // this creates road geometry 
    646                                          
    647                                         if (ndcs>5) { 
    648                                                 if (ndcs>6) { //  road & forest overlap - order of removal is important 
    649                                                         trig->removeInternalTriangles(forestroad.get()); 
    650                                                         trig->removeInternalTriangles(forestroad2.get()); 
    651                                                         trig->removeInternalTriangles(forestroad3.get()); 
    652                                                 } 
    653                                                 trig->removeInternalTriangles(forest.get()); 
    654                                                 forest->setTexture("forestRoof.png");  
    655                                                 osg::ref_ptr<osg::Vec3Array> locpts=forest->getPoints(points); 
    656                                                 geode->addDrawable(forest->makeAreal(locpts.get())); 
    657  
    658                                                 forest->setWallTexture("forestEdge.png");  
    659                                                 geode->addDrawable(forest->makeWallGeometry(locpts.get()) ); 
    660                                                 for (osg::Vec3Array::iterator vit=(*locpts).begin(); vit!=(*locpts).end(); vit++) { 
    661                                                         (*vit)+=osg::Vec3(0,0,30); 
    662                                                 } 
    663  
    664                                                 if (ndcs>6) {//  road & forest overlap 
    665                                                         forestroad->setTexture ("road.png"); 
    666                                                         forestroad->setTexrep(40,22); // texture is repeated at this frequency 
    667                                                         geode->addDrawable(forestroad->makeGeometry(points)); // this creates road geometry 
    668                                                         forestroad2->setTexture ("road.png"); 
    669                                                         forestroad2->setTexrep(40,22); // texture is repeated at this frequency 
    670                                                         geode->addDrawable(forestroad2->makeGeometry(points)); // this creates road geometry 
    671                                                         forestroad3->setTexture ("road.png"); 
    672                                                         forestroad3->setTexrep(40,22); // texture is repeated at this frequency 
    673                                                         geode->addDrawable(forestroad3->makeGeometry(points)); // this creates road geometry 
    674                                                         if (ndcs>7) {//  several overlapping DC's - add geom 
    675                                                                 trig->removeInternalTriangles(dc6.get()); 
    676                                                                 //                                                      dc6->makeDrawable(); 
    677                                                                 //                                                      dc6a->makeDrawable(); 
    678                                                                 dc6->setTexture ("road.png"); 
    679                                                                 dc6->setTexrep(40,22); // texture is repeated at this frequency 
    680                                                                 geode->addDrawable(dc6->makeGeometry(points)); // this creates road geometry 
    681                                                                 trig->removeInternalTriangles(dc6a.get()); 
    682                                                                 dc6a->setTexture ("road.png"); 
    683                                                                 dc6a->setTexrep(40,22); // texture is repeated at this frequency 
    684                                                                 geode->addDrawable(dc6a->makeGeometry(points)); // this creates road geometry 
    685                                                                 if (dc8.valid()) { 
    686                                                                         trig->removeInternalTriangles(dc8.get()); 
    687                                                                         dc8->setTexture ("road.png"); 
    688                                                                         dc8->setTexrep(40,16); // texture is repeated at this frequency 
    689                                                                         geode->addDrawable(dc8->makeGeometry(points)); // this creates road geometry 
    690                                                                 } 
    691                                                         } 
    692                                                 } 
    693                                         } 
    694                                 } 
    695                         } 
    696                 } 
    697         } 
    698         grp->addChild(geode.get()); 
     339    // ndcs is the number of delaunay constraints to be applied 
     340    osg::ref_ptr<osg::Group> grp=new osg::Group; 
     341    osg::ref_ptr<osg::Geode> geode=new osg::Geode; 
     342    osg::ref_ptr<osgUtil::DelaunayTriangulator> trig=new osgUtil::DelaunayTriangulator(); 
     343    osg::StateSet *stateset=geode->getOrCreateStateSet(); 
     344     
     345    osg::Vec3Array *points=new osg::Vec3Array; 
     346     
     347    osg::Image* image = osgDB::readImageFile("Lands-Flowers-Small_Purple.png"); 
     348    if (image) 
     349    { 
     350        osg::Texture2D* texture = new osg::Texture2D; 
     351        texture->setImage(image); 
     352        texture->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
     353        texture->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
     354        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); 
     355    } 
     356     
     357    geode->setStateSet( stateset ); 
     358    unsigned int i; 
     359     
     360    int eod=0; 
     361    while (eod>=0) { 
     362        osg::Vec3d pos=getpt(eod); 
     363        if (pos.z()>-10000) { 
     364            points->push_back(pos); 
     365            eod++; 
     366        } else { 
     367            eod=-9999; 
     368        } 
     369    } 
     370    std::vector < pyramid* > pyrlist; 
     371    osg::ref_ptr<WallConstraint> wc; // This example does not remove the interior 
     372    osg::ref_ptr<ArealConstraint> dc2; 
     373    osg::ref_ptr<ArealConstraint> forest; 
     374    osg::ref_ptr<LinearConstraint> dc3; 
     375    osg::ref_ptr<LinearConstraint> dc6; 
     376    osg::ref_ptr<LinearConstraint> dc6a; 
     377    osg::ref_ptr<LinearConstraint> dc8; 
     378    osg::ref_ptr<LinearConstraint> forestroad; 
     379    osg::ref_ptr<LinearConstraint> forestroad2; 
     380    osg::ref_ptr<LinearConstraint> forestroad3; 
     381    osg::ref_ptr<osgUtil::DelaunayConstraint> dc; 
     382    std::ostringstream what; 
     383    if (1==1) { // add a simple constraint of few points 
     384        osg::ref_ptr<osgUtil::DelaunayConstraint> dc=new osgUtil::DelaunayConstraint; 
     385        osg::Vec3Array *bounds=new osg::Vec3Array; 
     386        unsigned int nmax=4; 
     387        for (i=0 ; i<nmax; i++) { 
     388            float x=910.0+800.0*(i)/(float)nmax,y=810.0+6000*(i-1)*(i-1)/(float)(nmax*nmax); 
     389            bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
     390        } 
     391        dc->setVertexArray(bounds); 
     392        dc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,nmax) ); 
     393         
     394        trig->addInputConstraint(dc.get()); 
     395        what << nmax << " point simple constraint\n"; 
     396    } 
     397    if (ndcs>0) { // add 5 pyramids 
     398        for (unsigned int ipy=0; ipy<5/*5*/; ipy++) { 
     399            osg::ref_ptr<pyramid> pyr=new pyramid; 
     400            float x=2210+ipy*120, y=1120+ipy*220; 
     401            pyr->setpos(osg::Vec3(x,y,getheight(x,y)),125.0+10*ipy); 
     402            pyr->calcVertices(); // make vertices 
     403            pyr->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,4) ); 
     404            trig->addInputConstraint(pyr.get()); 
     405            pyrlist.push_back(pyr.get()); 
     406        } 
     407        what << 5 << " pyramids\n"; 
     408        if (ndcs>1) { 
     409            // add a simple constraint feature - this can cut holes in the terrain or just leave the triangles 
     410            // with edges forced to the constraint. 
     411            dc=new osgUtil::DelaunayConstraint; 
     412            osg::Vec3Array *bounds=new osg::Vec3Array; 
     413            for (i=0 ; i<12; i++) { 
     414                float x=610.0+420*sin(i/3.0),y=610.0+420*cos(i/3.0); 
     415                bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
     416            } 
     417            dc->setVertexArray(bounds); 
     418            dc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,12) ); 
     419             
     420            trig->addInputConstraint(dc.get()); 
     421            what << 12 << " point closed loop"; 
     422             
     423            if (ndcs>2) { 
     424                wc=new WallConstraint; // This example does not remove the interior 
     425                // eg to force terrain edges that are on ridges in the terrain etc. 
     426                // use wireframe to see the constrained edges. 
     427                // NB this is not necessarily a closed loop of edges. 
     428                // we do however build a wall at the coordinates. 
     429                bounds=new osg::Vec3Array; 
     430                for (i=0 ; i<5; i++) { 
     431                    float x=1610.0+420*sin(i/1.0),y=1610.0+420*cos(i/1.0); 
     432                    bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
     433                } 
     434                wc->setVertexArray(bounds); 
     435                wc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,5) ); 
     436                wc->setHeight(12.0); 
     437                trig->addInputConstraint(wc.get()); 
     438                what << " with interior removed\n"; 
     439                what << 5 << " point wall derived constraint\n"; 
     440                 
     441                if (ndcs>3) { 
     442                    // add a removed area and replace it with a different texture 
     443                    dc2=new ArealConstraint; 
     444                    bounds=new osg::Vec3Array; 
     445                    for (i=0 ; i<18; i++) { 
     446                        float x=1610.0+420*sin(i/3.0),y=610.0+220*cos(i/3.0); 
     447                        bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
     448                    } 
     449                    dc2->setVertexArray(bounds); 
     450                    dc2->setTexrep(100,100); // texture is repeated at this frequency 
     451                    dc2->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,18) ); 
     452                    trig->addInputConstraint(dc2.get()); 
     453                    what << 18 << " point area replaced\n"; 
     454                     
     455                    if (ndcs>4) { 
     456                        dc3=new LinearConstraint; 
     457                        // a linear feature or 'road' 
     458                        osg::Vec3Array *verts=new osg::Vec3Array; 
     459                        for (i=0 ; i<32; i++) { 
     460                            float x=610.0+50*i+90*sin(i/5.0),y=1110.0+90*cos(i/5.0); 
     461                            verts->push_back(osg::Vec3(x,y,getheight(x,y))); 
     462                        } 
     463                        dc3->setVertices(verts,9.5); // width of road 
     464                        for (osg::Vec3Array::iterator vit=points->begin(); vit!=points->end(); ) { 
     465                            if (dc3->contains(*vit)) { 
     466                                vit=points->erase(vit); 
     467                            } else { 
     468                                vit++; 
     469                            } 
     470                        } 
     471                        trig->addInputConstraint(dc3.get()); 
     472                        what << 32 << " point road constraint\n"; 
     473                        if (ndcs>5) { 
     474                            // add a removed area and replace it with a 'forest' with textured roof and walls 
     475                            forest=new ArealConstraint; 
     476                            bounds=new osg::Vec3Array; 
     477                            for (i=0 ; i<12; i++) { 
     478                                float x=610.0+420*sin(i/2.0),y=1810.0+420*cos(i/2.0); 
     479                                bounds->push_back(osg::Vec3(x,y,getheight(x,y))); 
     480                            } 
     481                            forest->setVertexArray(bounds); 
     482                            forest->setHeight(50); 
     483                            forest->setWallTexrep(100,50); 
     484                            forest->setTexrep(100,100); // texture is repeated at this frequency 
     485                            forest->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,12) ); 
     486                            if (ndcs==6) trig->addInputConstraint(forest.get()); 
     487                            what << 12 << " point forest constraint\n"; 
     488                             
     489                            if (ndcs>6) { // add roads that intersect forest 
     490                                osg::ref_ptr<osgUtil::DelaunayConstraint> forestplus=new osgUtil::DelaunayConstraint; 
     491                                forestroad=new LinearConstraint; 
     492                                verts=new osg::Vec3Array; 
     493                                for (i=0 ; i<12; i++) { 
     494                                    int ip=(i-6)*(i-6); 
     495                                    float xp=410.0+20.0*ip; 
     496                                    float y=1210.0+150*i; 
     497                                    verts->push_back(osg::Vec3(xp,y,getheight(xp,y))); 
     498                                } 
     499                                forestroad->setVertices(verts,22); // add road 
     500                                forestplus->merge(forestroad.get()); 
     501                                forestroad2=new LinearConstraint; 
     502                                verts=new osg::Vec3Array; 
     503                                for (i=0 ; i<12; i++) { 
     504                                    int ip=(i-6)*(i-6); 
     505                                    float xp=810.0-10.0*ip; 
     506                                    float y=1010.0+150*i; 
     507                                    verts->push_back(osg::Vec3(xp,y,getheight(xp,y))); 
     508                                } 
     509                                forestroad2->setVertices(verts,22); // add road 
     510                                forestplus->merge(forestroad2.get()); 
     511                                forestroad3=new LinearConstraint; 
     512                                verts=new osg::Vec3Array; 
     513                                for (i=0 ; i<6; i++) { 
     514                                    int ip=(i-6)*(i-6); 
     515                                    float xp=210.0+140.0*i+ip*10.0; 
     516                                    float y=1510.0+150*i; 
     517                                    verts->push_back(osg::Vec3(xp,y,getheight(xp,y))); 
     518                                } 
     519                                forestroad3->setVertices(verts,22); // add road 
     520                                forestplus->merge(forestroad3.get()); 
     521                                forestplus->merge(forest.get()); 
     522                                forestplus->handleOverlaps(); 
     523                                for (osg::Vec3Array::iterator vit=points->begin(); vit!=points->end(); ) { 
     524                                    if (forestroad->contains(*vit)) { 
     525                                        vit=points->erase(vit); 
     526                                    } else if (forestroad2->contains(*vit)) { 
     527                                        vit=points->erase(vit); 
     528                                    } else if (forestroad3->contains(*vit)) { 
     529                                        vit=points->erase(vit); 
     530                                    } else { 
     531                                        vit++; 
     532                                    } 
     533                                } 
     534                                trig->addInputConstraint(forestplus.get()); 
     535                                what << " roads intersect forest constraint\n"; 
     536                                if (ndcs>7) { 
     537                                    // this option adds a more complex DC 
     538                                    // made of several (ok 2 - extend your own way) overlapping DC's 
     539                                    osg::ref_ptr<osgUtil::DelaunayConstraint> dcoverlap=new osgUtil::DelaunayConstraint; 
     540                                    float x=1200; float y=1900; 
     541                                    { 
     542                                        verts=new osg::Vec3Array; 
     543                                        dc6=new LinearConstraint; 
     544                                        verts->push_back(osg::Vec3(x-180,y,getheight(x-180,y))); 
     545                                        verts->push_back(osg::Vec3(x+180,y,getheight(x+180,y))); 
     546                                        dc6->setVertices(verts,22); // width of road 
     547                                        dcoverlap->merge(dc6.get()); 
     548                                    } 
     549                                    { 
     550                                        dc6a= new LinearConstraint; 
     551                                        verts=new osg::Vec3Array; 
     552                                        verts->push_back(osg::Vec3(x,y-180,getheight(x,y-180))); 
     553                                        verts->push_back(osg::Vec3(x-20,y,getheight(x,y))); 
     554                                        verts->push_back(osg::Vec3(x,y+180,getheight(x,y+180))); 
     555                                        dc6a->setVertices(verts,22); // width of road 
     556                                        dcoverlap->merge(dc6a.get()); 
     557                                    } 
     558                                    what << "2 intersecting roads, with added points\n"; 
     559                                    if (ndcs>9) { 
     560                                        // add yet more roads 
     561                                        dc8= new LinearConstraint; 
     562                                        verts=new osg::Vec3Array; 
     563                                        float rad=60.0; 
     564                                        for (float theta=0; theta<4*osg::PI; theta+=0.1*osg::PI) { 
     565                                            float xp=x+rad*cos(theta), yp=y+rad*sin(theta); 
     566                                            verts->push_back(osg::Vec3(xp,yp,getheight(xp,yp))); 
     567                                            rad+=2.5; 
     568                                        } 
     569                                        dc8->setVertices(verts,16); // width of road 
     570                                        dcoverlap->merge(dc8.get()); 
     571                                        what << "Spiral road crosses several other constraints."; 
     572                                    } 
     573                                    dcoverlap->handleOverlaps(); 
     574                                    if (ndcs>8) { 
     575                                        // remove vertices cleans up the texturing at the intersection. 
     576                                        dcoverlap->removeVerticesInside(dc6.get()); 
     577                                        dcoverlap->removeVerticesInside(dc6a.get()); 
     578                                        if (dc8.valid()) dcoverlap->removeVerticesInside(dc8.get()); 
     579                                        what << "    remove internal vertices to improve texturing."; 
     580                                    } 
     581                                    for (osg::Vec3Array::iterator vit=points->begin(); vit!=points->end(); ) { 
     582                                        if (dcoverlap->contains(*vit)) { 
     583                                            vit=points->erase(vit); 
     584                                        } else { 
     585                                            vit++; 
     586                                        } 
     587                                    } 
     588                                    trig->addInputConstraint(dcoverlap.get()); 
     589                                } 
     590                            } 
     591                        } 
     592                    } 
     593                } 
     594            } 
     595        } 
     596    } // ndcs>0 
     597    trig->setInputPointArray(points); 
     598     
     599    /** NB you need to supply a vec3 array for the triangulator to calculate normals into */ 
     600    osg::Vec3Array *norms=new osg::Vec3Array; 
     601    trig->setOutputNormalArray(norms); 
     602     
     603    trig->triangulate(); 
     604    osg::notify(osg::WARN) << " End of trig\n " <<std::endl; 
     605     
     606    // Calculate the texture coordinates after triangulation as  
     607    //the points may get disordered by the triangulate function 
     608    osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; 
     609    gm->setVertexArray(points); // points may have been modified in order by triangulation. 
     610    /** calculate texture coords for terrain points */ 
     611    if (image) { 
     612        float repeat=150.0, ry=150.0; // how often to repeat texture 
     613        osg::Vec2Array *tcoords=new osg::Vec2Array; 
     614        for (osg::Vec3Array::iterator itr=points->begin(); itr!=points->end(); itr++) { 
     615            osg::Vec2 tcatxy((*itr).x()/repeat,(*itr).y()/ry); 
     616            tcoords->push_back(tcatxy); 
     617        } 
     618        gm->setTexCoordArray(0,tcoords); 
     619    } 
     620    gm->addPrimitiveSet(trig->getTriangles()); 
     621    gm->setNormalArray(trig->getOutputNormalArray()); 
     622    gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
     623    geode->addDrawable(gm.get()); 
     624    if (ndcs>0) { 
     625        for ( std::vector < pyramid* >::iterator itr=pyrlist.begin(); itr!=pyrlist.end(); itr++) { 
     626            trig->removeInternalTriangles(*itr); 
     627            geode->addDrawable((*itr)->makeGeometry()); // this fills the holes of each pyramid with geometry 
     628        } 
     629         
     630        if (ndcs>2) { 
     631            trig->removeInternalTriangles(dc.get()); 
     632             
     633            wc->setTexture("Brick-Norman-Brown.TGA"); // wall looks like brick 
     634            geode->addDrawable(wc->makeWallGeometry()); // this creates wall at wc drawarrays 
     635            if (ndcs>3) { 
     636                trig->removeInternalTriangles(dc2.get()); 
     637                osg::ref_ptr<osg::Vec3Array> arpts=dc2->getPoints(points); 
     638                dc2->setTexture("Lands-Needles_2.png"); 
     639                geode->addDrawable(dc2->makeAreal(arpts.get())); // this creates fill in geometry 
     640                 
     641                if (ndcs>4) { // a simple "road" 
     642                    trig->removeInternalTriangles(dc3.get()); 
     643                    dc3->setTexture ("road.png"); 
     644                    dc3->setTexrep(40,9.5); // texture is repeated at this frequency 
     645                    geode->addDrawable(dc3->makeGeometry(points)); // this creates road geometry 
     646                     
     647                    if (ndcs>5) { 
     648                        if (ndcs>6) { //  road & forest overlap - order of removal is important 
     649                            trig->removeInternalTriangles(forestroad.get()); 
     650                            trig->removeInternalTriangles(forestroad2.get()); 
     651                            trig->removeInternalTriangles(forestroad3.get()); 
     652                        } 
     653                        trig->removeInternalTriangles(forest.get()); 
     654                        forest->setTexture("forestRoof.png");  
     655                        osg::ref_ptr<osg::Vec3Array> locpts=forest->getPoints(points); 
     656                        geode->addDrawable(forest->makeAreal(locpts.get())); 
     657 
     658                        forest->setWallTexture("forestEdge.png");  
     659                        geode->addDrawable(forest->makeWallGeometry(locpts.get()) ); 
     660                        for (osg::Vec3Array::iterator vit=(*locpts).begin(); vit!=(*locpts).end(); vit++) { 
     661                            (*vit)+=osg::Vec3(0,0,30); 
     662                        } 
     663 
     664                        if (ndcs>6) {//  road & forest overlap 
     665                            forestroad->setTexture ("road.png"); 
     666                            forestroad->setTexrep(40,22); // texture is repeated at this frequency 
     667                            geode->addDrawable(forestroad->makeGeometry(points)); // this creates road geometry 
     668                            forestroad2->setTexture ("road.png"); 
     669                            forestroad2->setTexrep(40,22); // texture is repeated at this frequency 
     670                            geode->addDrawable(forestroad2->makeGeometry(points)); // this creates road geometry 
     671                            forestroad3->setTexture ("road.png"); 
     672                            forestroad3->setTexrep(40,22); // texture is repeated at this frequency 
     673                            geode->addDrawable(forestroad3->makeGeometry(points)); // this creates road geometry 
     674                            if (ndcs>7) {//  several overlapping DC's - add geom 
     675                                trig->removeInternalTriangles(dc6.get()); 
     676                                //                            dc6->makeDrawable(); 
     677                                //                            dc6a->makeDrawable(); 
     678                                dc6->setTexture ("road.png"); 
     679                                dc6->setTexrep(40,22); // texture is repeated at this frequency 
     680                                geode->addDrawable(dc6->makeGeometry(points)); // this creates road geometry 
     681                                trig->removeInternalTriangles(dc6a.get()); 
     682                                dc6a->setTexture ("road.png"); 
     683                                dc6a->setTexrep(40,22); // texture is repeated at this frequency 
     684                                geode->addDrawable(dc6a->makeGeometry(points)); // this creates road geometry 
     685                                if (dc8.valid()) { 
     686                                    trig->removeInternalTriangles(dc8.get()); 
     687                                    dc8->setTexture ("road.png"); 
     688                                    dc8->setTexrep(40,16); // texture is repeated at this frequency 
     689                                    geode->addDrawable(dc8->makeGeometry(points)); // this creates road geometry 
     690                                } 
     691                            } 
     692                        } 
     693                    } 
     694                } 
     695            } 
     696        } 
     697    } 
     698    grp->addChild(geode.get()); 
    699699    grp->addChild(createHUD(ndcs,what.str())); 
    700         return grp.release(); 
     700    return grp.release(); 
    701701} 
    702702 
     
    706706     
    707707    KeyboardEventHandler(osg::Node *nd,osgProducer::Viewer &vr): 
    708           _scene(nd), viewer(vr), iview(0) {} 
    709            
    710           virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) 
    711           { 
    712                   switch(ea.getEventType()) 
    713                   { 
    714                   case(osgGA::GUIEventAdapter::KEYDOWN): 
    715                           { 
    716                                   if (_scene && ea.getKey()=='n') 
    717                                   { 
    718                                           // re-tesselate the scene graph.  
    719                                           // the same contours are re-tesselated using a new method. Old contours  
    720                                           // & tesselation type are held internally in the derived Geode class tesselateDemoGeometry. 
    721                                           //     cxTesselateVisitor tsv; 
    722                                           //   _scene->accept(tsv); 
    723                                           iview++; 
    724                                           if (iview>10) iview=0; 
    725                                           osg::ref_ptr<osg::Node> loadedModel = makedelaunay(iview); 
    726                                           viewer.setSceneData(loadedModel.get()); 
    727                                           return true; 
    728                                   } 
    729                                   break; 
    730                           } 
    731                   default: 
    732                           break; 
    733                   } 
    734                   return false; 
    735           } 
    736            
    737           virtual void accept(osgGA::GUIEventHandlerVisitor& v) 
    738           { 
    739                   v.visit(*this); 
    740           } 
    741            
    742           osg::Node *_scene; 
    743           osgProducer::Viewer &viewer; 
    744           int iview; 
     708      _scene(nd), viewer(vr), iview(0) {} 
     709       
     710      virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) 
     711      { 
     712          switch(ea.getEventType()) 
     713          { 
     714          case(osgGA::GUIEventAdapter::KEYDOWN): 
     715              { 
     716                  if (_scene && ea.getKey()=='n') 
     717                  { 
     718                      // re-tesselate the scene graph.  
     719                      // the same contours are re-tesselated using a new method. Old contours  
     720                      // & tesselation type are held internally in the derived Geode class tesselateDemoGeometry. 
     721                      //     cxTesselateVisitor tsv; 
     722                      //   _scene->accept(tsv); 
     723                      iview++; 
     724                      if (iview>10) iview=0; 
     725                      osg::ref_ptr<osg::Node> loadedModel = makedelaunay(iview); 
     726                      viewer.setSceneData(loadedModel.get()); 
     727                      return true; 
     728                  } 
     729                  break; 
     730              } 
     731          default: 
     732              break; 
     733          } 
     734          return false; 
     735      } 
     736       
     737      virtual void accept(osgGA::GUIEventHandlerVisitor& v) 
     738      { 
     739          v.visit(*this); 
     740      } 
     741       
     742      osg::Node *_scene; 
     743      osgProducer::Viewer &viewer; 
     744      int iview; 
    745745}; 
    746746int main( int argc, char **argv ) 
    747747{ 
    748          
     748     
    749749    // use an ArgumentParser object to manage the program arguments. 
    750750    osg::ArgumentParser arguments(&argc,argv); 
     
    761761    arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindigs."); 
    762762     
    763          
     763     
    764764    // construct the viewer. 
    765765    osgProducer::Viewer viewer(arguments); 
    766          
     766     
    767767    // set up the value with sensible default event handlers. 
    768768    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); 
    769          
     769     
    770770    // get details on keyboard and mouse bindings used by the viewer. 
    771771    viewer.getUsage(*arguments.getApplicationUsage()); 
    772          
     772     
    773773    // if user request help write it out to cout. 
    774774    bool helpAll = arguments.read("--help-all"); 
    775775    unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) | 
    776                 ((helpAll ||  arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) | 
    777                 ((helpAll ||  arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 ); 
     776        ((helpAll ||  arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) | 
     777        ((helpAll ||  arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 ); 
    778778    if (helpType) 
    779779    { 
     
    781781        return 1; 
    782782    } 
    783          
     783     
    784784    // report any errors if they have occured when parsing the program aguments. 
    785785    if (arguments.errors()) 
     
    794794        return 1; 
    795795    } 
    796          
     796     
    797797    osg::Timer_t start_tick = osg::Timer::instance()->tick(); 
    798          
     798     
    799799    // create the scene from internal specified terrain/constraints. 
    800800    osg::ref_ptr<osg::Node> loadedModel = makedelaunay(0); 
    801          
     801     
    802802    // if no model has been successfully loaded report failure. 
    803803    if (!loadedModel)  
     
    806806        return 1; 
    807807    } 
    808          
    809          
     808     
     809     
    810810    // any option left unread are converted into errors to write out later. 
    811811    arguments.reportRemainingOptionsAsUnrecognized(); 
    812          
     812     
    813813    // report any errors if they have occured when parsing the program aguments. 
    814814    if (arguments.errors()) 
     
    816816        arguments.writeErrorMessages(std::cout); 
    817817    } 
    818          
     818     
    819819    osg::Timer_t end_tick = osg::Timer::instance()->tick(); 
    820          
     820     
    821821    std::cout << "Time to load = "<<osg::Timer::instance()->delta_s(start_tick,end_tick)<<std::endl; 
    822          
     822     
    823823    // optimize the scene graph, remove rendundent nodes and state etc. 
    824824    osgUtil::Optimizer optimizer; 
    825825    optimizer.optimize(loadedModel.get()); 
    826          
     826     
    827827    // pass the loaded scene graph to the viewer. 
    828828    viewer.setSceneData(loadedModel.get()); 
    829          
     829     
    830830    // copied from osgtessealte.cpp 
    831         // add event handler for keyboard 'n' to retriangulate 
     831    // add event handler for keyboard 'n' to retriangulate 
    832832    viewer.getEventHandlerList().push_front(new KeyboardEventHandler(loadedModel.get(), viewer)); 
    833          
     833     
    834834    // create the windows and run the threads. 
    835835    viewer.realize(); 
    836          
     836     
    837837    while( !viewer.done() ) 
    838838    { 
    839839        // wait for all cull and draw threads to complete. 
    840840        viewer.sync(); 
    841                  
     841         
    842842        // update the scene by traversing it with the the update visitor which will 
    843843        // call all node update callbacks and animations. 
    844844        viewer.update(); 
    845                  
     845         
    846846        // fire off the cull and draw traversals of the scene. 
    847847        viewer.frame(); 
     
    851851    // wait for all cull and draw threads to complete before exit. 
    852852    viewer.sync(); 
    853          
     853     
    854854    return 0; 
    855855} 
    856856 
    857 osg::Vec3Array * WallConstraint::getWall(const osg::Vec3Array *points,const float height) const 
     857osg::Vec3Array * WallConstraint::getWall(const float height) const 
    858858{ // return array of points for a wall height high around the constraint 
    859         osg::Vec3Array *wall=new osg::Vec3Array; 
    860         if (height>0.0) { 
    861                 osg::Vec3 off(0,0,height); 
    862                 const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    863                 for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
    864                         const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
    865                         if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP || 
    866                                 prset->getMode()==osg::PrimitiveSet::LINE_STRIP) { // nothing else loops 
    867                                 // start with the last point on the loop 
    868                                 for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
    869                                         const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    870                                         wall->push_back(curp); 
    871                                         wall->push_back(curp+off); 
    872                                 } 
    873                                 const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
    874                                 wall->push_back(curp); 
    875                                 wall->push_back(curp+off); 
    876                         } 
    877                 } 
    878         } 
    879         return wall; 
    880 } 
    881 osg::Vec2Array * WallConstraint::getWallTexcoords(const osg::Vec3Array *points,const float height) const 
     859    osg::Vec3Array *wall=new osg::Vec3Array; 
     860    if (height>0.0) { 
     861        osg::Vec3 off(0,0,height); 
     862        const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     863        for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
     864            const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
     865            if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP || 
     866                prset->getMode()==osg::PrimitiveSet::LINE_STRIP) { // nothing else loops 
     867                // start with the last point on the loop 
     868                for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
     869                    const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     870                    wall->push_back(curp); 
     871                    wall->push_back(curp+off); 
     872                } 
     873                const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
     874                wall->push_back(curp); 
     875                wall->push_back(curp+off); 
     876            } 
     877        } 
     878    } 
     879    return wall; 
     880} 
     881osg::Vec2Array * WallConstraint::getWallTexcoords(const float height) const 
    882882{ // return array of points for a wall height high around the constraint 
    883         osg::Vec2Array *tcoords= NULL; 
    884         if (height>0.0) { 
    885                 float texrepRound=txxrepWall; 
    886                 tcoords= new osg::Vec2Array; 
    887                 float circumference=0; // distance around wall to get exact number of repeats of texture 
    888                 const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    889                 for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
    890                         const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
    891                         osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
     883    osg::Vec2Array *tcoords= NULL; 
     884    if (height>0.0) { 
     885        float texrepRound=txxrepWall; 
     886        tcoords= new osg::Vec2Array; 
     887        float circumference=0; // distance around wall to get exact number of repeats of texture 
     888        const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     889        for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
     890            const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
     891            osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
    892892                        unsigned int i; 
    893                         for (i=0; i<prset->getNumIndices(); i++) { 
    894                                 const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    895                                 circumference+=(curp-prevp).length(); 
    896                                 prevp=curp; 
    897                         } 
    898                         const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
    899                         circumference+=(curp-prevp).length(); 
    900                          
    901                         int nround=(int)(circumference/txxrepWall); 
    902                         if (nround<1) nround=1; // at least one repeat. 
    903                         texrepRound=circumference/nround; 
    904                          
    905                         float ds=0; 
    906                         prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
    907                         if (tcoords) { 
    908                                 for (i=0; i<prset->getNumIndices(); i++) { 
    909                                         const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    910                                         osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
    911                                         tcoords->push_back(tci); 
    912                                         tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
    913                                         tcoords->push_back(tci); 
    914                                         ds+=(curp-prevp).length(); 
    915                                         prevp=curp; 
    916                                 } 
    917                                 osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
    918                                 tcoords->push_back(tci); 
    919                                 tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
    920                                 tcoords->push_back(tci); 
    921                         } 
    922                 } // per primitiveset 
    923                  
    924         } 
    925         return tcoords; 
    926 } 
    927 osg::Geometry *WallConstraint::makeWallGeometry(const osg::Vec3Array *points) const 
     893            for (i=0; i<prset->getNumIndices(); i++) { 
     894                const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     895                circumference+=(curp-prevp).length(); 
     896                prevp=curp; 
     897            } 
     898            const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
     899            circumference+=(curp-prevp).length(); 
     900             
     901            int nround=(int)(circumference/txxrepWall); 
     902            if (nround<1) nround=1; // at least one repeat. 
     903            texrepRound=circumference/nround; 
     904             
     905            float ds=0; 
     906            prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
     907            if (tcoords) { 
     908                for (i=0; i<prset->getNumIndices(); i++) { 
     909                    const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     910                    osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
     911                    tcoords->push_back(tci); 
     912                    tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
     913                    tcoords->push_back(tci); 
     914                    ds+=(curp-prevp).length(); 
     915                    prevp=curp; 
     916                } 
     917                osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
     918                tcoords->push_back(tci); 
     919                tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
     920                tcoords->push_back(tci); 
     921            } 
     922        } // per primitiveset 
     923         
     924    } 
     925    return tcoords; 
     926} 
     927osg::Geometry *WallConstraint::makeWallGeometry() const 
    928928{ 
    929         osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the wall 
    930         if (texture!="") { 
    931                 osg::Image* image = osgDB::readImageFile(texture.c_str()); 
    932                 if (image) 
    933                 { 
    934                         osg::Texture2D* txt = new osg::Texture2D; 
    935                         osg::StateSet* stateset = gm->getOrCreateStateSet(); 
    936                         txt->setImage(image); 
    937                         txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
    938                         txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP ); 
    939                         stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
    940                         osg::Material* material = new osg::Material; 
    941                         material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,0.0f,1.0f)); 
    942                         material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    943                         stateset->setAttribute(material,osg::StateAttribute::ON); 
    944                         stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
    945                 } 
    946         } 
    947         gm->setVertexArray(getWall(points,height)); 
    948         gm->addPrimitiveSet(makeWall()); 
    949         gm->setTexCoordArray(0,getWallTexcoords(points,height)); 
    950         gm->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
    951         gm->setNormalArray(getWallNormals(points)); // this creates normals to walls 
    952          
    953         return gm.release(); 
    954 } 
    955  
    956 osg::Vec3Array *ArealConstraint::getWallNormals(const osg::Vec3Array *points) const 
     929    osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the wall 
     930    if (texture!="") { 
     931        osg::Image* image = osgDB::readImageFile(texture.c_str()); 
     932        if (image) 
     933        { 
     934            osg::Texture2D* txt = new osg::Texture2D; 
     935            osg::StateSet* stateset = gm->getOrCreateStateSet(); 
     936            txt->setImage(image); 
     937            txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
     938            txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP ); 
     939            stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
     940            osg::Material* material = new osg::Material; 
     941            material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,0.0f,1.0f)); 
     942            material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     943            stateset->setAttribute(material,osg::StateAttribute::ON); 
     944            stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
     945        } 
     946    } 
     947    gm->setVertexArray(getWall(height)); 
     948    gm->addPrimitiveSet(makeWall()); 
     949    gm->setTexCoordArray(0,getWallTexcoords(height)); 
     950    gm->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); 
     951    gm->setNormalArray(getWallNormals()); // this creates normals to walls 
     952     
     953    return gm.release(); 
     954} 
     955 
     956osg::Vec3Array *ArealConstraint::getWallNormals() const 
    957957{ 
    958         osg::Vec3Array *nrms=new osg::Vec3Array; 
    959         const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    960         for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
    961                 const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
    962                 if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP) { // nothing else loops 
    963                         // start with the last point on the loop 
    964                         osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
    965                         for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
    966                                 const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    967                                 osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
    968                                 nrm.normalize(); 
    969                                 nrms->push_back(nrm); 
    970                                 nrms->push_back(nrm); 
    971                                 prevp=curp; 
    972                         } 
    973                         const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
    974                         osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
    975                         nrm.normalize(); 
    976                         nrms->push_back(nrm); 
    977                         nrms->push_back(nrm); 
    978                 } 
    979         } 
    980         return nrms; 
    981 } 
    982  
    983  
    984 osg::Vec3Array * ArealConstraint::getWall(const osg::Vec3Array* points,const float height) const 
     958    osg::Vec3Array *nrms=new osg::Vec3Array; 
     959    const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     960    for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
     961        const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
     962        if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP) { // nothing else loops 
     963            // start with the last point on the loop 
     964            osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
     965            for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
     966                const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     967                osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
     968                nrm.normalize(); 
     969                nrms->push_back(nrm); 
     970                nrms->push_back(nrm); 
     971                prevp=curp; 
     972            } 
     973            const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
     974            osg::Vec3 nrm=(curp-prevp)^osg::Vec3(0,0,1); 
     975            nrm.normalize(); 
     976            nrms->push_back(nrm); 
     977            nrms->push_back(nrm); 
     978        } 
     979    } 
     980    return nrms; 
     981} 
     982 
     983 
     984osg::Vec3Array * ArealConstraint::getWall(const float height) const 
    985985{ // return array of points for a wall height high around the constraint 
    986         osg::Vec3Array *wall=new osg::Vec3Array; 
    987         if (height>0.0) { 
    988                 osg::Vec3 off(0,0,height); 
    989                 const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    990                 for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
    991                         const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
    992                         if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP) { // nothing else loops 
    993                                 // start with the last point on the loop 
    994                                 for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
    995                                         const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    996                                         wall->push_back(curp); 
    997                                         wall->push_back(curp+off); 
    998                                 } 
    999                                 const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
    1000                                 wall->push_back(curp); 
    1001                                 wall->push_back(curp+off); 
    1002                         } 
    1003                 } 
    1004         } 
    1005         return wall; 
    1006 } 
    1007  
    1008 osg::Vec2Array * ArealConstraint::getWallTexcoords(const osg::Vec3Array *points,const float height) const 
     986    osg::Vec3Array *wall=new osg::Vec3Array; 
     987    if (height>0.0) { 
     988        osg::Vec3 off(0,0,height); 
     989        const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     990        for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
     991            const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
     992            if (prset->getMode()==osg::PrimitiveSet::LINE_LOOP) { // nothing else loops 
     993                // start with the last point on the loop 
     994                for (unsigned int i=0; i<prset->getNumIndices(); i++) { 
     995                    const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     996                    wall->push_back(curp); 
     997                    wall->push_back(curp+off); 
     998                } 
     999                const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
     1000                wall->push_back(curp); 
     1001                wall->push_back(curp+off); 
     1002            } 
     1003        } 
     1004    } 
     1005    return wall; 
     1006} 
     1007 
     1008osg::Vec2Array * ArealConstraint::getWallTexcoords(const float height) const 
    10091009{ // return array of points for a wall height high around the constraint 
    1010         osg::Vec2Array *tcoords= NULL; 
    1011         if (height>0.0) { 
    1012                 float texrepRound=txxrepWall; 
    1013                 tcoords= new osg::Vec2Array; 
    1014                 float circumference=0; // distance around wall to get exact number of repeats of texture 
    1015                 const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    1016                 for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
    1017                         const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
    1018                         osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
     1010    osg::Vec2Array *tcoords= NULL; 
     1011    if (height>0.0) { 
     1012        float texrepRound=txxrepWall; 
     1013        tcoords= new osg::Vec2Array; 
     1014        float circumference=0; // distance around wall to get exact number of repeats of texture 
     1015        const osg::Vec3Array *vertices= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     1016        for (unsigned int ipr=0; ipr<getNumPrimitiveSets(); ipr++) { 
     1017            const osg::PrimitiveSet* prset=getPrimitiveSet(ipr); 
     1018            osg::Vec3 prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
    10191019                        unsigned int i; 
    1020                         for (i=0; i<prset->getNumIndices(); i++) { 
    1021                                 const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    1022                                 circumference+=(curp-prevp).length(); 
    1023                                 prevp=curp; 
    1024                         } 
    1025                         const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
    1026                         circumference+=(curp-prevp).length(); 
    1027                          
    1028                         int nround=(int)(circumference/txxrepWall); 
    1029                         if (nround<1) nround=1; // at least one repeat. 
    1030                         texrepRound=circumference/nround; 
    1031                          
    1032                         float ds=0; 
    1033                         prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
    1034                         if (tcoords) { 
    1035                                 for (i=0; i<prset->getNumIndices(); i++) { 
    1036                                         const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
    1037                                         osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
    1038                                         tcoords->push_back(tci); 
    1039                                         tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
    1040                                         tcoords->push_back(tci); 
    1041                                         ds+=(curp-prevp).length(); 
    1042                                         prevp=curp; 
    1043                                 } 
    1044                                 osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
    1045                                 tcoords->push_back(tci); 
    1046                                 tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
    1047                                 tcoords->push_back(tci); 
    1048                         } 
    1049                 } // per primitiveset 
    1050         } 
    1051         return tcoords; 
     1020            for (i=0; i<prset->getNumIndices(); i++) { 
     1021                const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     1022                circumference+=(curp-prevp).length(); 
     1023                prevp=curp; 
     1024            } 
     1025            const osg::Vec3 curp=(*vertices)[prset->index (0)]; 
     1026            circumference+=(curp-prevp).length(); 
     1027             
     1028            int nround=(int)(circumference/txxrepWall); 
     1029            if (nround<1) nround=1; // at least one repeat. 
     1030            texrepRound=circumference/nround; 
     1031             
     1032            float ds=0; 
     1033            prevp=(*vertices)[prset->index (prset->getNumIndices()-1)]; 
     1034            if (tcoords) { 
     1035                for (i=0; i<prset->getNumIndices(); i++) { 
     1036                    const osg::Vec3 curp=(*vertices)[prset->index (i)]; 
     1037                    osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
     1038                    tcoords->push_back(tci); 
     1039                    tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
     1040                    tcoords->push_back(tci); 
     1041                    ds+=(curp-prevp).length(); 
     1042                    prevp=curp; 
     1043                } 
     1044                osg::Vec2 tci=osg::Vec2f(ds/texrepRound,0/txyrepWall); 
     1045                tcoords->push_back(tci); 
     1046                tci=osg::Vec2f(ds/texrepRound,height/txyrepWall); 
     1047                tcoords->push_back(tci); 
     1048            } 
     1049        } // per primitiveset 
     1050    } 
     1051    return tcoords; 
    10521052} 
    10531053osg::DrawArrays* ArealConstraint::makeCanopy( void ) const 
    10541054{ 
    1055         return (new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,3*_interiorTris.size())); 
     1055    return (new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,3*_interiorTris.size())); 
    10561056} 
    10571057osg::Vec3Array *ArealConstraint::getCanopy(const osg::Vec3Array *points,const float height) const 
    10581058{ // returns the array of vertices in the canopy 
    1059         osg::Vec3 off(0,0,height); 
    1060         osg::Vec3Array *internals=new osg::Vec3Array; 
    1061         trilist::const_iterator tritr; 
    1062         for (tritr=_interiorTris.begin(); tritr!=_interiorTris.end();tritr++) { 
    1063                 for (int i=0; i<3; i++) { 
    1064                         int index=(*tritr)[i]; 
    1065                         internals->push_back((*points)[index]+off); 
    1066                 } 
    1067         } 
    1068         return internals; 
     1059    osg::Vec3 off(0,0,height); 
     1060    osg::Vec3Array *internals=new osg::Vec3Array; 
     1061    trilist::const_iterator tritr; 
     1062    for (tritr=_interiorTris.begin(); tritr!=_interiorTris.end();tritr++) { 
     1063        for (int i=0; i<3; i++) { 
     1064            int index=(*tritr)[i]; 
     1065            internals->push_back((*points)[index]+off); 
     1066        } 
     1067    } 
     1068    return internals; 
    10691069} 
    10701070osg::Vec3Array *ArealConstraint::getCanopyNormals(const osg::Vec3Array *points) const 
    10711071{ 
    1072         osg::Vec3Array *nrms=new osg::Vec3Array; 
    1073         trilist::const_iterator tritr; 
    1074         for (tritr=_interiorTris.begin(); tritr!=_interiorTris.end();tritr++) { 
    1075                 osg::Vec3 e1=(*points)[(*tritr)[1]]-(*points)[(*tritr)[0]]; 
    1076                 osg::Vec3 e2=(*points)[(*tritr)[2]]-(*points)[(*tritr)[0]]; 
    1077                 osg::Vec3 nrm=e1^e2; 
    1078                 nrm.normalize(); 
    1079                 nrms->push_back(nrm); 
    1080         } 
    1081         return nrms; 
     1072    osg::Vec3Array *nrms=new osg::Vec3Array; 
     1073    trilist::const_iterator tritr; 
     1074    for (tritr=_interiorTris.begin(); tritr!=_interiorTris.end();tritr++) { 
     1075        osg::Vec3 e1=(*points)[(*tritr)[1]]-(*points)[(*tritr)[0]]; 
     1076        osg::Vec3 e2=(*points)[(*tritr)[2]]-(*points)[(*tritr)[0]]; 
     1077        osg::Vec3 nrm=e1^e2; 
     1078        nrm.normalize(); 
     1079        nrms->push_back(nrm); 
     1080    } 
     1081    return nrms; 
    10821082} 
    10831083 
    10841084osg::Vec2Array *ArealConstraint::getCanopyTexcoords(const osg::Vec3Array *points) const 
    10851085{ 
    1086         osg::Vec3Array::const_iterator tritr; 
    1087         osg::ref_ptr<osg::Vec2Array> tcoords= new osg::Vec2Array ; 
    1088         for (tritr=points->begin(); tritr!=points->end();tritr++) { 
    1089                                 // calculate tcoords for terrain from xy drape. 
    1090                 osg::Vec2 tci=osg::Vec2f(tritr->x()/txxrepArea, tritr->y()/txyrepArea); 
    1091                 tcoords->push_back(tci); 
    1092         } 
    1093         return tcoords.release(); 
     1086    osg::Vec3Array::const_iterator tritr; 
     1087    osg::ref_ptr<osg::Vec2Array> tcoords= new osg::Vec2Array ; 
     1088    for (tritr=points->begin(); tritr!=points->end();tritr++) { 
     1089                // calculate tcoords for terrain from xy drape. 
     1090        osg::Vec2 tci=osg::Vec2f(tritr->x()/txxrepArea, tritr->y()/txyrepArea); 
     1091        tcoords->push_back(tci); 
     1092    } 
     1093    return tcoords.release(); 
    10941094} 
    10951095 
    10961096osg::DrawArrays * ArealConstraint::makeWall(void) const 
    10971097{ // build a wall height high around the constraint 
    1098         const osg::Vec3Array *_line= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
    1099         return (new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,2+2*_line->size())); 
     1098    const osg::Vec3Array *_line= dynamic_cast<const osg::Vec3Array*>(getVertexArray()); 
     1099    return (new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,2+2*_line->size())); 
    11001100} 
    11011101 
    11021102osg::Geometry *ArealConstraint::makeWallGeometry( osg::Vec3Array *pt)  
    11031103{ 
    1104         osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the wall 
    1105         osg::ref_ptr<osg::Geometry> edges=new osg::Geometry; // edges of bounds 
    1106         edges->setVertexArray(pt); 
    1107         osg::DrawElementsUInt *trgeom=getTriangles(); 
    1108         edges->addPrimitiveSet(trgeom); 
    1109          
    1110         osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator; // this assembles all the constraints 
    1111         tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
    1112         tscx->setBoundaryOnly(true); 
    1113         tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NONZERO);  
    1114         //  find all edges. 
    1115         const osg::Vec3Array *points=dynamic_cast<osg::Vec3Array*>(getVertexArray()); 
    1116          
    1117         tscx->retesselatePolygons(*(edges)); // find all edges 
    1118          
    1119         if (walltexture!="") { 
    1120                 osg::Image* image = osgDB::readImageFile(walltexture.c_str()); 
    1121                 if (image) 
    1122                 { 
    1123                         osg::Texture2D* txt = new osg::Texture2D; 
    1124                         osg::StateSet* stateset = gm->getOrCreateStateSet(); 
    1125                         txt->setImage(image); 
    1126                         txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
    1127                         txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP ); 
    1128                         stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
    1129                 } 
    1130         } 
    1131         points=dynamic_cast<osg::Vec3Array*>(edges->getVertexArray()); 
    1132         int nstart=0; 
    1133         osg::ref_ptr<osg::Vec3Array> coords=new osg::Vec3Array; 
    1134         osg::ref_ptr<osg::Vec2Array> tcoords=new osg::Vec2Array; 
    1135         for (unsigned int i=0; i<edges->getNumPrimitiveSets(); i++) { 
    1136                 osg::PrimitiveSet *pr=edges->getPrimitiveSet(i); 
    1137                 if (pr->getMode() == osg::PrimitiveSet::LINE_LOOP) { 
    1138                         float ds=0; 
    1139                         for (unsigned int icon=0; icon<pr->getNumIndices(); icon++) { 
    1140                                 unsigned int ithis=pr->index(icon); 
    1141                                 osg::Vec3 pt=                           (*points)[ithis]; 
    1142                                 coords->push_back(pt); 
    1143                                 coords->push_back(pt+osg::Vec3(0,0,height)); 
    1144                                 tcoords->push_back(osg::Vec2(ds/txxrepWall,0)); 
    1145                                 tcoords->push_back(osg::Vec2(ds/txxrepWall,1.0)); 
    1146                                 if (icon<pr->getNumIndices()-1) ds+=((*points)[pr->index(icon+1)]-(*points)[ithis]).length(); 
    1147                                 else ds+=((*points)[pr->index(0)]-(*points)[ithis]).length(); 
    1148                         } 
    1149                         // repeat first point 
    1150                         unsigned int ithis=pr->index(0); 
    1151                         coords->push_back((*points)[ithis]); 
    1152                         coords->push_back((*points)[ithis]+osg::Vec3(0,0,height)); 
    1153                         tcoords->push_back(osg::Vec2(ds/txxrepWall,0)); 
    1154                         tcoords->push_back(osg::Vec2(ds/txxrepWall,1.0)); 
    1155                         gm->setVertexArray(coords.get()); 
    1156                         gm->setTexCoordArray(0,tcoords.get()); 
    1157                         gm->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,nstart,2+2*pr->getNumIndices())); 
    1158                         nstart+=2+2*pr->getNumIndices(); 
    1159                 } 
    1160         } 
    1161          
    1162         return gm.release(); 
     1104    osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the wall 
     1105    osg::ref_ptr<osg::Geometry> edges=new osg::Geometry; // edges of bounds 
     1106    edges->setVertexArray(pt); 
     1107    osg::DrawElementsUInt *trgeom=getTriangles(); 
     1108    edges->addPrimitiveSet(trgeom); 
     1109     
     1110    osg::ref_ptr<osgUtil::Tesselator> tscx=new osgUtil::Tesselator; // this assembles all the constraints 
     1111    tscx->setTesselationType(osgUtil::Tesselator::TESS_TYPE_GEOMETRY); 
     1112    tscx->setBoundaryOnly(true); 
     1113    tscx->setWindingType( osgUtil::Tesselator::TESS_WINDING_NONZERO);  
     1114    //  find all edges. 
     1115    const osg::Vec3Array *points=dynamic_cast<osg::Vec3Array*>(getVertexArray()); 
     1116     
     1117    tscx->retesselatePolygons(*(edges)); // find all edges 
     1118     
     1119    if (walltexture!="") { 
     1120        osg::Image* image = osgDB::readImageFile(walltexture.c_str()); 
     1121        if (image) 
     1122        { 
     1123            osg::Texture2D* txt = new osg::Texture2D; 
     1124            osg::StateSet* stateset = gm->getOrCreateStateSet(); 
     1125            txt->setImage(image); 
     1126            txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
     1127            txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP ); 
     1128            stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
     1129        } 
     1130    } 
     1131    points=dynamic_cast<osg::Vec3Array*>(edges->getVertexArray()); 
     1132    int nstart=0; 
     1133    osg::ref_ptr<osg::Vec3Array> coords=new osg::Vec3Array; 
     1134    osg::ref_ptr<osg::Vec2Array> tcoords=new osg::Vec2Array; 
     1135    for (unsigned int i=0; i<edges->getNumPrimitiveSets(); i++) { 
     1136        osg::PrimitiveSet *pr=edges->getPrimitiveSet(i); 
     1137        if (pr->getMode() == osg::PrimitiveSet::LINE_LOOP) { 
     1138            float ds=0; 
     1139            for (unsigned int icon=0; icon<pr->getNumIndices(); icon++) { 
     1140                unsigned int ithis=pr->index(icon); 
     1141                osg::Vec3 pt=                (*points)[ithis]; 
     1142                coords->push_back(pt); 
     1143                coords->push_back(pt+osg::Vec3(0,0,height)); 
     1144                tcoords->push_back(osg::Vec2(ds/txxrepWall,0)); 
     1145                tcoords->push_back(osg::Vec2(ds/txxrepWall,1.0)); 
     1146                if (icon<pr->getNumIndices()-1) ds+=((*points)[pr->index(icon+1)]-(*points)[ithis]).length(); 
     1147                else ds+=((*points)[pr->index(0)]-(*points)[ithis]).length(); 
     1148            } 
     1149            // repeat first point 
     1150            unsigned int ithis=pr->index(0); 
     1151            coords->push_back((*points)[ithis]); 
     1152            coords->push_back((*points)[ithis]+osg::Vec3(0,0,height)); 
     1153            tcoords->push_back(osg::Vec2(ds/txxrepWall,0)); 
     1154            tcoords->push_back(osg::Vec2(ds/txxrepWall,1.0)); 
     1155            gm->setVertexArray(coords.get()); 
     1156            gm->setTexCoordArray(0,tcoords.get()); 
     1157            gm->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,nstart,2+2*pr->getNumIndices())); 
     1158            nstart+=2+2*pr->getNumIndices(); 
     1159        } 
     1160    } 
     1161     
     1162    return gm.release(); 
    11631163} 
    11641164 
     
    11661166osg::Geometry * ArealConstraint::makeAreal( osg::Vec3Array *points)  
    11671167{ 
    1168         osg::ref_ptr<osg::Geometry> gm; // the fill in area 
    1169         if (_interiorTris.size()>0) { 
    1170                 gm =new osg::Geometry; // the forest roof 
    1171                 gm->setVertexArray(points); 
    1172                 osg::DrawElementsUInt *trgeom=getTriangles(); 
    1173                 gm->addPrimitiveSet(trgeom); 
    1174                 gm->setTexCoordArray(0,getCanopyTexcoords(points)); 
    1175                 osg::Image* image = osgDB::readImageFile(texture); 
    1176                 if (image) 
    1177                 { 
    1178                         osg::Texture2D* txt = new osg::Texture2D; 
    1179                         osg::StateSet* stateset = gm->getOrCreateStateSet(); 
    1180                         txt->setImage(image); 
    1181                         txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
    1182                         txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
    1183                         stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
    1184                         osg::Material* material = new osg::Material; 
    1185                         material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    1186                         material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    1187                         stateset->setAttribute(material,osg::StateAttribute::ON); 
    1188                         stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
    1189                 } 
    1190         } 
    1191         return gm.release(); 
     1168    osg::ref_ptr<osg::Geometry> gm; // the fill in area 
     1169    if (_interiorTris.size()>0) { 
     1170        gm =new osg::Geometry; // the forest roof 
     1171        gm->setVertexArray(points); 
     1172        osg::DrawElementsUInt *trgeom=getTriangles(); 
     1173        gm->addPrimitiveSet(trgeom); 
     1174        gm->setNormalArray(getCanopyNormals(points)); 
     1175        gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
     1176        gm->setTexCoordArray(0,getCanopyTexcoords(points)); 
     1177        osg::Image* image = osgDB::readImageFile(texture); 
     1178        if (image) 
     1179        { 
     1180            osg::Texture2D* txt = new osg::Texture2D; 
     1181            osg::StateSet* stateset = gm->getOrCreateStateSet(); 
     1182            txt->setImage(image); 
     1183            txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
     1184            txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
     1185            stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
     1186            osg::Material* material = new osg::Material; 
     1187            material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     1188            material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     1189            stateset->setAttribute(material,osg::StateAttribute::ON); 
     1190            stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
     1191        } 
     1192    } 
     1193    return gm.release(); 
    11921194} 
    11931195 
     
    11951197void LinearConstraint::setVertices( osg::Vec3Array *lp, const float w) 
    11961198{ // generate constant width around line (calls setvertices(edges)) 
    1197         osg::ref_ptr<osg::Vec3Array> edges=new osg::Vec3Array; 
    1198         _tcoords=new osg::Vec2Array; // texture coordinates for replacement geometry 
    1199         _edgecoords=new osg::Vec3Array; // posiiton coordinates for replacement geometry 
    1200         width=w; 
    1201         _midline=lp; 
    1202         float ds=0; 
    1203         for(unsigned int i=0;i<lp->size();i++) { 
    1204                 osg::Vec3 valong; 
    1205                 osg::Vec3 pos[2]; 
    1206                  
    1207                 if (i==0) { 
    1208                         valong=(*lp)[i+1]-(*lp)[i]; 
    1209                 } else if (i==lp->size()-1) { 
    1210                         valong=(*lp)[i]-(*lp)[i-1]; 
    1211                 } else { 
    1212                         valong=(*lp)[i+1]-(*lp)[i-1]; 
    1213                 } 
    1214                 valong.normalize(); 
    1215                 osg::Vec3 vperp=valong^osg::Vec3(0,0,1); 
    1216                 pos[0]=(*lp)[i]-vperp*.5*width; 
    1217                 pos[1]=(*lp)[i]+vperp*.5*width; 
    1218                 edges->push_back(pos[0]); 
    1219                 _edgecoords->push_back(pos[0]); 
    1220                 _tcoords->push_back(osg::Vec2(0/txyrepAcross,ds/txxrepAlong)); 
    1221                 edges->insert(edges->begin() ,pos[1]); 
    1222                 _edgecoords->insert(_edgecoords->begin() ,pos[1]); 
    1223                 _tcoords->insert(_tcoords->begin() ,osg::Vec2(width/txyrepAcross,ds/txxrepAlong)); 
    1224                 if (i<lp->size()-1) ds+=((*lp)[i+1]-(*lp)[i]).length(); 
    1225         } 
    1226         setVertexArray(edges.get()); 
    1227         addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,edges->size()) ); 
     1199    osg::ref_ptr<osg::Vec3Array> edges=new osg::Vec3Array; 
     1200    _tcoords=new osg::Vec2Array; // texture coordinates for replacement geometry 
     1201    _edgecoords=new osg::Vec3Array; // posiiton coordinates for replacement geometry 
     1202    width=w; 
     1203    _midline=lp; 
     1204    float ds=0; 
     1205    for(unsigned int i=0;i<lp->size();i++) { 
     1206        osg::Vec3 valong; 
     1207        osg::Vec3 pos[2]; 
     1208         
     1209        if (i==0) { 
     1210            valong=(*lp)[i+1]-(*lp)[i]; 
     1211        } else if (i==lp->size()-1) { 
     1212            valong=(*lp)[i]-(*lp)[i-1]; 
     1213        } else { 
     1214            valong=(*lp)[i+1]-(*lp)[i-1]; 
     1215        } 
     1216        valong.normalize(); 
     1217        osg::Vec3 vperp=valong^osg::Vec3(0,0,1); 
     1218        pos[0]=(*lp)[i]-vperp*.5*width; 
     1219        pos[1]=(*lp)[i]+vperp*.5*width; 
     1220        edges->push_back(pos[0]); 
     1221        _edgecoords->push_back(pos[0]); 
     1222        _tcoords->push_back(osg::Vec2(0/txyrepAcross,ds/txxrepAlong)); 
     1223        edges->insert(edges->begin() ,pos[1]); 
     1224        _edgecoords->insert(_edgecoords->begin() ,pos[1]); 
     1225        _tcoords->insert(_tcoords->begin() ,osg::Vec2(width/txyrepAcross,ds/txxrepAlong)); 
     1226        if (i<lp->size()-1) ds+=((*lp)[i+1]-(*lp)[i]).length(); 
     1227    } 
     1228    setVertexArray(edges.get()); 
     1229    addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,edges->size()) ); 
    12281230} 
    12291231 
    12301232osg::DrawArrays* LinearConstraint::makeRoad(void ) const 
    12311233{ 
    1232         return  new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,2*_midline->size()); 
    1233          
     1234    return     new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,2*_midline->size()); 
     1235     
    12341236} 
    12351237 
    12361238osg::Vec3Array *LinearConstraint::getRoadNormals(const osg::Vec3Array *points) const 
    12371239{ 
    1238         osg::Vec3Array *nrms=new osg::Vec3Array; 
    1239         for(unsigned int i=0;i<_midline->size();i++) { 
    1240                 osg::Vec3 valong; // vector along midline of road 
    1241                 if (i==0) { 
    1242                         valong=(*_midline)[i+1]-(*_midline)[i]; 
    1243                 } else if (i==_midline->size()-1) { 
    1244                         valong=(*_midline)[i]-(*_midline)[i-1]; 
    1245                 } else { 
    1246                         valong=(*_midline)[i+1]-(*_midline)[i-1]; 
    1247                 } 
    1248                 osg::Vec3 vperp=valong^osg::Vec3(0,0,1); 
    1249                 osg::Vec3 nrm=vperp^valong; // normal to linear 
    1250                 nrm.normalize(); 
    1251                 nrms->push_back(nrm); // repeated for each vertex of linear. 
    1252                 nrms->push_back(nrm); 
    1253         } 
    1254         return nrms; 
    1255 } 
    1256 osg::Vec3Array *LinearConstraint::getRoadVertices(const osg::Vec3Array *points) const 
     1240    osg::Vec3Array *nrms=new osg::Vec3Array; 
     1241    for(unsigned int i=0;i<_midline->size();i++) { 
     1242        osg::Vec3 valong; // vector along midline of road 
     1243        if (i==0) { 
     1244            valong=(*_midline)[i+1]-(*_midline)[i]; 
     1245        } else if (i==_midline->size()-1) { 
     1246            valong=(*_midline)[i]-(*_midline)[i-1]; 
     1247        } else { 
     1248            valong=(*_midline)[i+1]-(*_midline)[i-1]; 
     1249        } 
     1250        osg::Vec3 vperp=valong^osg::Vec3(0,0,1); 
     1251        osg::Vec3 nrm=vperp^valong; // normal to linear 
     1252        nrm.normalize(); 
     1253        nrms->push_back(nrm); // repeated for each vertex of linear. 
     1254        nrms->push_back(nrm); 
     1255    } 
     1256    return nrms; 
     1257} 
     1258osg::Vec3Array *LinearConstraint::getRoadVertices() const 
    12571259{ 
    1258         osg::Vec3Array *linearEdges=new osg::Vec3Array; 
    1259         for(unsigned int i=0;i<_midline->size();i++) { 
    1260                 osg::Vec3 valong; // vector along midline of road 
    1261                 if (i==0) { 
    1262                         valong=(*_midline)[i+1]-(*_midline)[i]; 
    1263                 } else if (i==_midline->size()-1) { 
    1264                         valong=(*_midline)[i]-(*_midline)[i-1]; 
    1265                 } else { 
    1266                         valong=(*_midline)[i+1]-(*_midline)[i-1]; 
    1267                 } 
    1268                 valong.normalize(); 
    1269                 osg::Vec3 vperp=valong^osg::Vec3(0,0,1); // vector across road 
    1270                 // sides of linear 
    1271                 linearEdges->push_back((*_midline)[i]-vperp*.5*width); 
    1272                 linearEdges->push_back((*_midline)[i]+vperp*.5*width); 
    1273         } 
    1274         return linearEdges; 
     1260    osg::Vec3Array *linearEdges=new osg::Vec3Array; 
     1261    for(unsigned int i=0;i<_midline->size();i++) { 
     1262        osg::Vec3 valong; // vector along midline of road 
     1263        if (i==0) { 
     1264            valong=(*_midline)[i+1]-(*_midline)[i]; 
     1265        } else if (i==_midline->size()-1) { 
     1266            valong=(*_midline)[i]-(*_midline)[i-1]; 
     1267        } else { 
     1268            valong=(*_midline)[i+1]-(*_midline)[i-1]; 
     1269        } 
     1270        valong.normalize(); 
     1271        osg::Vec3 vperp=valong^osg::Vec3(0,0,1); // vector across road 
     1272        // sides of linear 
     1273        linearEdges->push_back((*_midline)[i]-vperp*.5*width); 
     1274        linearEdges->push_back((*_midline)[i]+vperp*.5*width); 
     1275    } 
     1276    return linearEdges; 
    12751277} 
    12761278 
    12771279osg::Vec2Array *LinearConstraint::getRoadTexcoords(const osg::Vec3Array *points)  { 
    1278         // need to create a vec2 array from the coordinates that fits the road 
    1279         osg::Vec3Array::const_iterator tritr; 
    1280         osg::ref_ptr<osg::Vec2Array> tcoords= new osg::Vec2Array ; 
    1281         for (tritr=points->begin(); tritr!=points->end();tritr++) { 
    1282                 osg::Vec2 tci(-1.,-1.); 
    1283                 int ib=0; 
    1284                 // osg::Vec3Array *varr=dynamic_cast<osg::Vec3Array*>(getVertexArray()); 
    1285                 bool ptfound=false; 
    1286                 for (osg::Vec3Array::iterator vit=_edgecoords->begin(); vit!= _edgecoords->end() && !ptfound; vit++) { 
    1287                         if ((*vit)==(*tritr)) { 
    1288                                 tci=_tcoords->at(ib); 
    1289                                 ptfound=true; 
    1290                         } 
    1291                         ib++; 
    1292                 } 
    1293                 if (!ptfound) { // search for surrounding points and interpolate 
    1294                         ib=0; 
    1295                         osg::Vec3 pminus=(_edgecoords->back()); // need pminus for interpolation 
    1296                         int ibm1=_edgecoords->size()-1; 
    1297                         for (osg::Vec3Array::iterator vit=_edgecoords->begin(); vit!= _edgecoords->end() /*&& !ptfound*/; vit++) { 
    1298                                 osg::Vec3 pplus=(*vit)-(*tritr); 
    1299                                 osg::Vec3 dpm=pminus-(*tritr); 
    1300                                 pplus.set (pplus.x(),pplus.y(),0); 
    1301                                 dpm.set (dpm.x(),dpm.y(),0); 
    1302                                 float dprod=pplus*dpm/(pplus.length() * dpm.length()); 
    1303                                 if (dprod<-0.9999) { // *tritr lies between.... 
    1304                                         osg::Vec2 tminus=_tcoords->at(ibm1); 
    1305                                         osg::Vec2 tplus=_tcoords->at(ib); 
    1306                                         float frac=(dpm.length()/(dpm.length()+pplus.length())); 
    1307                                         tci=tminus+((tplus-tminus)*frac); 
    1308                                         ptfound=true; 
    1309                                 } 
    1310                                 ibm1=ib; 
    1311                                 ib++;    
    1312                                 pminus=(*vit); 
    1313                         } 
    1314                 } 
    1315                 tcoords->push_back(tci); 
    1316         } 
    1317         // some extra points are not interpolated as they lie between 2 interpolated vertices 
    1318         for (tritr=points->begin(); tritr!=points->end();tritr++) { 
    1319                 int ib=tritr-points->begin(); 
    1320                 osg::Vec2 tci=tcoords->at(ib); 
    1321                 if (tci.x()<-.99 && tci.y()<-.99) { 
    1322                         // search through each of the primitivesets 
    1323                         osg::Vec3Array::const_iterator ptitr; 
    1324                         //      osg::notify(osg::WARN) << "Not calculated " <<  (*tritr).x() <<"," << (*tritr).y() << std::endl; 
    1325                         for (ptitr=points->begin(); ptitr!=points->end();ptitr++) { 
    1326                         } 
    1327                 } 
    1328         } 
    1329         return tcoords.release(); 
     1280    // need to create a vec2 array from the coordinates that fits the road 
     1281    osg::Vec3Array::const_iterator tritr; 
     1282    osg::ref_ptr<osg::Vec2Array> tcoords= new osg::Vec2Array ; 
     1283    for (tritr=points->begin(); tritr!=points->end();tritr++) { 
     1284        osg::Vec2 tci(-1.,-1.); 
     1285        int ib=0; 
     1286        // osg::Vec3Array *varr=dynamic_cast<osg::Vec3Array*>(getVertexArray()); 
     1287        bool ptfound=false; 
     1288        for (osg::Vec3Array::iterator vit=_edgecoords->begin(); vit!= _edgecoords->end() && !ptfound; vit++) { 
     1289            if ((*vit)==(*tritr)) { 
     1290                tci=_tcoords->at(ib); 
     1291                ptfound=true; 
     1292            } 
     1293            ib++; 
     1294        } 
     1295        if (!ptfound) { // search for surrounding points and interpolate 
     1296            ib=0; 
     1297            osg::Vec3 pminus=(_edgecoords->back()); // need pminus for interpolation 
     1298            int ibm1=_edgecoords->size()-1; 
     1299            for (osg::Vec3Array::iterator vit=_edgecoords->begin(); vit!= _edgecoords->end() /*&& !ptfound*/; vit++) { 
     1300                osg::Vec3 pplus=(*vit)-(*tritr); 
     1301                osg::Vec3 dpm=pminus-(*tritr); 
     1302                pplus.set (pplus.x(),pplus.y(),0); 
     1303                dpm.set (dpm.x(),dpm.y(),0); 
     1304                float dprod=pplus*dpm/(pplus.length() * dpm.length()); 
     1305                if (dprod<-0.9999) { // *tritr lies between.... 
     1306                    osg::Vec2 tminus=_tcoords->at(ibm1); 
     1307                    osg::Vec2 tplus=_tcoords->at(ib); 
     1308                    float frac=(dpm.length()/(dpm.length()+pplus.length())); 
     1309                    tci=tminus+((tplus-tminus)*frac); 
     1310                    ptfound=true; 
     1311                } 
     1312                ibm1=ib; 
     1313                ib++;     
     1314                pminus=(*vit); 
     1315            } 
     1316        } 
     1317        tcoords->push_back(tci); 
     1318    } 
     1319    // some extra points are not interpolated as they lie between 2 interpolated vertices 
     1320    for (tritr=points->begin(); tritr!=points->end();tritr++) { 
     1321        int ib=tritr-points->begin(); 
     1322        osg::Vec2 tci=tcoords->at(ib); 
     1323        if (tci.x()<-.99 && tci.y()<-.99) { 
     1324            // search through each of the primitivesets 
     1325            osg::Vec3Array::const_iterator ptitr; 
     1326            //    osg::notify(osg::WARN) << "Not calculated " <<  (*tritr).x() <<"," << (*tritr).y() << std::endl; 
     1327            for (ptitr=points->begin(); ptitr!=points->end();ptitr++) { 
     1328            } 
     1329        } 
     1330    } 
     1331    return tcoords.release(); 
    13301332} 
    13311333osg::Vec3Array * LinearConstraint::getNormals(const osg::Vec3Array *points)  
    13321334{ 
    1333         osg::ref_ptr<osg::Vec3Array> norms=new osg::Vec3Array; 
    1334         for (osg::DrawElementsUInt::iterator uiitr=prim_tris_->begin(); uiitr!=prim_tris_->end();uiitr+=3) { 
    1335                 osg::Vec3 e1=(*points)[*(uiitr+1)]-(*points)[(*uiitr)]; 
    1336                 osg::Vec3 e2=(*points)[*(uiitr+2)]-(*points)[*(uiitr+1)]; 
    1337                 osg::Vec3 n=e1^e2; 
    1338                 n.normalize(); 
    1339                 //      if (n.z()<0) n=-n; 
    1340                 norms->push_back(n); 
    1341         } 
    1342         return norms.release(); 
     1335    osg::ref_ptr<osg::Vec3Array> norms=new osg::Vec3Array; 
     1336    for (osg::DrawElementsUInt::iterator uiitr=prim_tris_->begin(); uiitr!=prim_tris_->end();uiitr+=3) { 
     1337        osg::Vec3 e1=(*points)[*(uiitr+1)]-(*points)[(*uiitr)]; 
     1338        osg::Vec3 e2=(*points)[*(uiitr+2)]-(*points)[*(uiitr+1)]; 
     1339        osg::Vec3 n=e1^e2; 
     1340        n.normalize(); 
     1341        //    if (n.z()<0) n=-n; 
     1342        norms->push_back(n); 
     1343    } 
     1344    return norms.release(); 
    13431345} 
    13441346 
    13451347osg::Geometry * LinearConstraint::makeGeometry(const osg::Vec3Array *points)  
    13461348{ 
    1347         osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the fill in road/railway 
    1348         if (_midline->size()>0) { 
    1349                 osg::ref_ptr<osg::Vec3Array> locpts=getPoints(points); 
    1350                 if (texture!="") { 
    1351                         osg::Image* image = osgDB::readImageFile(texture.c_str()); 
    1352                         if (image) 
    1353                         { 
    1354                                 osg::Texture2D* txt = new osg::Texture2D; 
    1355                                 osg::StateSet* stateset = gm->getOrCreateStateSet(); 
    1356                                 txt->setImage(image); 
    1357                                 txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
    1358                                 txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
    1359                                 stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
    1360                                 osg::Material* material = new osg::Material; 
    1361                                 material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    1362                                 material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
    1363                                 stateset->setAttribute(material,osg::StateAttribute::ON); 
    1364                                 stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
    1365                         } 
    1366                         gm->setTexCoordArray(0,getRoadTexcoords(locpts.get())); 
    1367                 } 
    1368                 gm->setVertexArray(locpts.get()); 
    1369                 gm->setNormalArray(getNormals(locpts.get())); 
    1370                 gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
    1371                 gm->addPrimitiveSet(getTriangles()); 
    1372         } 
    1373          
    1374         return gm.release(); 
    1375          
    1376 } 
    1377  
    1378  
     1349    osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the fill in road/railway 
     1350    if (_midline->size()>0) { 
     1351        osg::ref_ptr<osg::Vec3Array> locpts=getPoints(points); 
     1352        if (texture!="") { 
     1353            osg::Image* image = osgDB::readImageFile(texture.c_str()); 
     1354            if (image) 
     1355            { 
     1356                osg::Texture2D* txt = new osg::Texture2D; 
     1357                osg::StateSet* stateset = gm->getOrCreateStateSet(); 
     1358                txt->setImage(image); 
     1359                txt->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 
     1360                txt->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 
     1361                stateset->setTextureAttributeAndModes(0,txt,osg::StateAttribute::ON); 
     1362                osg::Material* material = new osg::Material; 
     1363                material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     1364                material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     1365                stateset->setAttribute(material,osg::StateAttribute::ON); 
     1366                stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); 
     1367            } 
     1368            gm->setTexCoordArray(0,getRoadTexcoords(locpts.get())); 
     1369        } 
     1370        gm->setVertexArray(locpts.get()); 
     1371        gm->setNormalArray(getNormals(locpts.get())); 
     1372        gm->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE); 
     1373        gm->addPrimitiveSet(getTriangles()); 
     1374    } 
     1375     
     1376    return gm.release(); 
     1377     
     1378} 
     1379 
     1380 
     1381