- Timestamp:
- 10/27/05 11:37:38 (8 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/examples/osgdelaunay/osgdelaunay.cpp
r4611 r4621 35 35 */ 36 36 class WallConstraint: public osgUtil::DelaunayConstraint { // forces lines to eb edge 37 // wall constraint - can generate a wall at the coordinates of the constraint37 // wall constraint - can generate a wall at the coordinates of the constraint 38 38 public: 39 39 /** if you derive a class from DelaunayConstraint then you can create 40 40 * 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 constraint49 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 walls63 // start with the last point on the loop64 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 parameters86 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;} 92 92 protected: 93 float height;94 std::string texture;95 float txxrepWall, txyrepWall;93 float height; 94 std::string texture; 95 float txxrepWall, txyrepWall; 96 96 }; 97 97 class 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. 99 99 public: 100 100 /** if you derive a class from DelaunayConstraint then you can create 101 101 * 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 above118 * (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 parameters125 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; 134 134 protected: 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; 139 139 }; 140 140 … … 142 142 /** forces edges of a "road" to fit triangles 143 143 * 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. */ 145 145 public: 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 174 174 protected: 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 feature180 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. 181 181 }; 182 182 … … 185 185 class pyramid : public osgUtil::DelaunayConstraint { 186 186 /** 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. */ 188 188 public: 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) const189 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 194 194 { 195 // create pyramid geometry. Centre plus points around base196 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 first245 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 } 253 253 private: 254 osg::Vec3 _pos; // where the pyramid is255 float _side ; // length of side254 osg::Vec3 _pos; // where the pyramid is 255 float _side ; // length of side 256 256 }; 257 257 258 258 float getheight(const float x, const float y) 259 259 { // 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); 261 261 } 262 262 osg::Vec3d getpt(const int np) 263 263 { // 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); 273 273 } 274 274 osg::Node* createHUD(const int ndcs,std::string what) … … 277 277 278 278 std::string timesFont("fonts/arial.ttf"); 279 279 280 280 // turn lighting off for the text and disable depth test to ensure its always ontop. 281 281 osg::StateSet* stateset = geode->getOrCreateStateSet(); 282 282 stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 283 283 284 284 // Disable depth test, and make sure that the hud is drawn after everything 285 285 // else so that it always appears ontop. 286 286 stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); 287 287 stateset->setRenderBinDetails(11,"RenderBin"); 288 288 289 289 osg::Vec3 position(50.0f,900.0f,0.0f); 290 290 osg::Vec3 delta(0.0f,-35.0f,0.0f); 291 291 292 292 { 293 293 osgText::Text* text = new osgText::Text; 294 294 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 298 298 text->setFont(timesFont); 299 299 text->setPosition(position); … … 302 302 position += delta*(ndcs+2); 303 303 304 text = new osgText::Text;304 text = new osgText::Text; 305 305 geode->addDrawable( text ); 306 306 307 307 text->setFont(timesFont); 308 308 text->setPosition(position); … … 315 315 osgText::Text* text = new osgText::Text; 316 316 geode->addDrawable( text ); 317 317 318 318 text->setFont(timesFont); 319 319 text->setPosition(position); … … 321 321 322 322 } 323 323 324 324 // create the hud. 325 325 osg::MatrixTransform* modelview_abs = new osg::MatrixTransform; … … 327 327 modelview_abs->setMatrix(osg::Matrix::identity()); 328 328 modelview_abs->addChild(geode); 329 329 330 330 osg::Projection* projection = new osg::Projection; 331 331 projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); 332 332 projection->addChild(modelview_abs); 333 333 334 334 return projection; 335 335 336 336 } 337 337 osg::Group *makedelaunay(const int ndcs) 338 338 { // create a terrain tile. This is just an example! 339 // ndcs is the number of delaunay constraints to be applied340 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 interior372 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 points384 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 pyramids398 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 vertices403 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 triangles410 // 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 interior425 // 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 texture443 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 frequency451 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 road464 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 walls475 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 frequency485 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 forest490 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 road500 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 road510 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 road520 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 DC538 // made of several (ok 2 - extend your own way) overlapping DC's539 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 road547 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 road556 dcoverlap->merge(dc6a.get());557 }558 what << "2 intersecting roads, with added points\n";559 if (ndcs>9) {560 // add yet more roads561 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 road570 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>0597 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 as607 //the points may get disordered by the triangulate function608 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 texture613 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 geometry628 }629 630 if (ndcs>2) {631 trig->removeInternalTriangles(dc.get());632 633 wc->setTexture("Brick-Norman-Brown.TGA"); // wall looks like brick634 geode->addDrawable(wc->makeWallGeometry(points)); // this creates wall at wc drawarrays635 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 geometry640 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 frequency645 geode->addDrawable(dc3->makeGeometry(points)); // this creates road geometry646 647 if (ndcs>5) {648 if (ndcs>6) { // road & forest overlap - order of removal is important649 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 overlap665 forestroad->setTexture ("road.png");666 forestroad->setTexrep(40,22); // texture is repeated at this frequency667 geode->addDrawable(forestroad->makeGeometry(points)); // this creates road geometry668 forestroad2->setTexture ("road.png");669 forestroad2->setTexrep(40,22); // texture is repeated at this frequency670 geode->addDrawable(forestroad2->makeGeometry(points)); // this creates road geometry671 forestroad3->setTexture ("road.png");672 forestroad3->setTexrep(40,22); // texture is repeated at this frequency673 geode->addDrawable(forestroad3->makeGeometry(points)); // this creates road geometry674 if (ndcs>7) {// several overlapping DC's - add geom675 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 frequency680 geode->addDrawable(dc6->makeGeometry(points)); // this creates road geometry681 trig->removeInternalTriangles(dc6a.get());682 dc6a->setTexture ("road.png");683 dc6a->setTexrep(40,22); // texture is repeated at this frequency684 geode->addDrawable(dc6a->makeGeometry(points)); // this creates road geometry685 if (dc8.valid()) {686 trig->removeInternalTriangles(dc8.get());687 dc8->setTexture ("road.png");688 dc8->setTexrep(40,16); // texture is repeated at this frequency689 geode->addDrawable(dc8->makeGeometry(points)); // this creates road geometry690 }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()); 699 699 grp->addChild(createHUD(ndcs,what.str())); 700 return grp.release();700 return grp.release(); 701 701 } 702 702 … … 706 706 707 707 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 contours720 // & 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; 745 745 }; 746 746 int main( int argc, char **argv ) 747 747 { 748 748 749 749 // use an ArgumentParser object to manage the program arguments. 750 750 osg::ArgumentParser arguments(&argc,argv); … … 761 761 arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindigs."); 762 762 763 763 764 764 // construct the viewer. 765 765 osgProducer::Viewer viewer(arguments); 766 766 767 767 // set up the value with sensible default event handlers. 768 768 viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); 769 769 770 770 // get details on keyboard and mouse bindings used by the viewer. 771 771 viewer.getUsage(*arguments.getApplicationUsage()); 772 772 773 773 // if user request help write it out to cout. 774 774 bool helpAll = arguments.read("--help-all"); 775 775 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 ); 778 778 if (helpType) 779 779 { … … 781 781 return 1; 782 782 } 783 783 784 784 // report any errors if they have occured when parsing the program aguments. 785 785 if (arguments.errors()) … … 794 794 return 1; 795 795 } 796 796 797 797 osg::Timer_t start_tick = osg::Timer::instance()->tick(); 798 798 799 799 // create the scene from internal specified terrain/constraints. 800 800 osg::ref_ptr<osg::Node> loadedModel = makedelaunay(0); 801 801 802 802 // if no model has been successfully loaded report failure. 803 803 if (!loadedModel) … … 806 806 return 1; 807 807 } 808 809 808 809 810 810 // any option left unread are converted into errors to write out later. 811 811 arguments.reportRemainingOptionsAsUnrecognized(); 812 812 813 813 // report any errors if they have occured when parsing the program aguments. 814 814 if (arguments.errors()) … … 816 816 arguments.writeErrorMessages(std::cout); 817 817 } 818 818 819 819 osg::Timer_t end_tick = osg::Timer::instance()->tick(); 820 820 821 821 std::cout << "Time to load = "<<osg::Timer::instance()->delta_s(start_tick,end_tick)<<std::endl; 822 822 823 823 // optimize the scene graph, remove rendundent nodes and state etc. 824 824 osgUtil::Optimizer optimizer; 825 825 optimizer.optimize(loadedModel.get()); 826 826 827 827 // pass the loaded scene graph to the viewer. 828 828 viewer.setSceneData(loadedModel.get()); 829 829 830 830 // copied from osgtessealte.cpp 831 // add event handler for keyboard 'n' to retriangulate831 // add event handler for keyboard 'n' to retriangulate 832 832 viewer.getEventHandlerList().push_front(new KeyboardEventHandler(loadedModel.get(), viewer)); 833 833 834 834 // create the windows and run the threads. 835 835 viewer.realize(); 836 836 837 837 while( !viewer.done() ) 838 838 { 839 839 // wait for all cull and draw threads to complete. 840 840 viewer.sync(); 841 841 842 842 // update the scene by traversing it with the the update visitor which will 843 843 // call all node update callbacks and animations. 844 844 viewer.update(); 845 845 846 846 // fire off the cull and draw traversals of the scene. 847 847 viewer.frame(); … … 851 851 // wait for all cull and draw threads to complete before exit. 852 852 viewer.sync(); 853 853 854 854 return 0; 855 855 } 856 856 857 osg::Vec3Array * WallConstraint::getWall(const osg::Vec3Array *points,constfloat height) const857 osg::Vec3Array * WallConstraint::getWall(const float height) const 858 858 { // 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 loops867 // start with the last point on the loop868 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,constfloat height) const859 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 float height) const 882 882 { // 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 texture888 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)]; 892 892 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 primitiveset923 924 }925 return tcoords;926 } 927 osg::Geometry *WallConstraint::makeWallGeometry( const osg::Vec3Array *points) const893 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 928 928 { 929 osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the wall930 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 walls952 953 return gm.release();954 } 955 956 osg::Vec3Array *ArealConstraint::getWallNormals( const osg::Vec3Array *points) const929 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 956 osg::Vec3Array *ArealConstraint::getWallNormals() const 957 957 { 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 loops963 // start with the last point on the loop964 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,constfloat height) const958 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 float height) const 985 985 { // 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 loops993 // start with the last point on the loop994 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,constfloat height) const986 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 float height) const 1009 1009 { // 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 texture1015 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)]; 1019 1019 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 primitiveset1050 }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; 1052 1052 } 1053 1053 osg::DrawArrays* ArealConstraint::makeCanopy( void ) const 1054 1054 { 1055 return (new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,3*_interiorTris.size()));1055 return (new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,3*_interiorTris.size())); 1056 1056 } 1057 1057 osg::Vec3Array *ArealConstraint::getCanopy(const osg::Vec3Array *points,const float height) const 1058 1058 { // 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; 1069 1069 } 1070 1070 osg::Vec3Array *ArealConstraint::getCanopyNormals(const osg::Vec3Array *points) const 1071 1071 { 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; 1082 1082 } 1083 1083 1084 1084 osg::Vec2Array *ArealConstraint::getCanopyTexcoords(const osg::Vec3Array *points) const 1085 1085 { 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(); 1094 1094 } 1095 1095 1096 1096 osg::DrawArrays * ArealConstraint::makeWall(void) const 1097 1097 { // 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())); 1100 1100 } 1101 1101 1102 1102 osg::Geometry *ArealConstraint::makeWallGeometry( osg::Vec3Array *pt) 1103 1103 { 1104 osg::ref_ptr<osg::Geometry> gm=new osg::Geometry; // the wall1105 osg::ref_ptr<osg::Geometry> edges=new osg::Geometry; // edges of bounds1106 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 constraints1111 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 edges1118 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 point1150 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(); 1163 1163 } 1164 1164 … … 1166 1166 osg::Geometry * ArealConstraint::makeAreal( osg::Vec3Array *points) 1167 1167 { 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(); 1192 1194 } 1193 1195 … … 1195 1197 void LinearConstraint::setVertices( osg::Vec3Array *lp, const float w) 1196 1198 { // 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 geometry1199 _edgecoords=new osg::Vec3Array; // posiiton coordinates for replacement geometry1200 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()) ); 1228 1230 } 1229 1231 1230 1232 osg::DrawArrays* LinearConstraint::makeRoad(void ) const 1231 1233 { 1232 returnnew 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 1234 1236 } 1235 1237 1236 1238 osg::Vec3Array *LinearConstraint::getRoadNormals(const osg::Vec3Array *points) const 1237 1239 { 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 road1241 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 linear1250 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) const1240 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 } 1258 osg::Vec3Array *LinearConstraint::getRoadVertices() const 1257 1259 { 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 road1261 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 road1270 // sides of linear1271 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; 1275 1277 } 1276 1278 1277 1279 osg::Vec2Array *LinearConstraint::getRoadTexcoords(const osg::Vec3Array *points) { 1278 // need to create a vec2 array from the coordinates that fits the road1279 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 interpolate1294 ib=0;1295 osg::Vec3 pminus=(_edgecoords->back()); // need pminus for interpolation1296 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 vertices1318 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 primitivesets1323 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(); 1330 1332 } 1331 1333 osg::Vec3Array * LinearConstraint::getNormals(const osg::Vec3Array *points) 1332 1334 { 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(); 1343 1345 } 1344 1346 1345 1347 osg::Geometry * LinearConstraint::makeGeometry(const osg::Vec3Array *points) 1346 1348 { 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
