2005-10-25 21:28:48 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This application is open source and may be redistributed and / or modified
* freely and without restriction , both in commericial and non commericial applications ,
* as long as this copyright notice is maintained .
*
* This application is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
*/
/** Example of use of delaunay triangulator with constraints.
* this could be a method of generating terrains , a constraint forces certain edges to
* exist in the triangulation .
*/
# include <osgDB/ReadFile>
# include <osgUtil/Optimizer>
# include <osgProducer/Viewer>
# include <osg/CoordinateSystemNode>
# include <osgUtil/DelaunayTriangulator>
# include <osg/Material>
# include <osg/Texture2D>
# include <osg/Projection>
# include <osg/MatrixTransform>
# include <osgUtil/Tesselator> // tesselator triangulates the constrained triangles
# include <osgText/Text>
# include <sstream>
/** here are 2 common types of constraint
* Area - forces an area to be filled ; replacement geometry is a canopy and optional wall
* Linear - constructs a closed loop of constant width around a line .
*/
class WallConstraint : public osgUtil : : DelaunayConstraint { // forces lines to eb edge
2005-10-27 17:37:38 +08:00
// wall constraint - can generate a wall at the coordinates of the constraint
2005-10-25 21:28:48 +08:00
public :
/** if you derive a class from DelaunayConstraint then you can create
* a specific geometry creation routine .
2005-10-27 17:37:38 +08:00
*/
WallConstraint ( ) : height ( 0 ) , txxrepWall ( 10 ) , txyrepWall ( 10 ) { }
/** or create a wall around the constraint area: */
virtual osg : : Geometry * makeWallGeometry ( void ) const ;
/** for basic purposes, you can call these routines to make simple fill in geometries */
virtual osg : : DrawArrays * makeWall ( void ) const { // build a wall height high around the constraint
const osg : : Vec3Array * _line = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
return ( new osg : : DrawArrays ( osg : : PrimitiveSet : : QUAD_STRIP , 0 , 2 * _line - > size ( ) ) ) ;
}
virtual osg : : Vec3Array * getWall ( const float height ) const ;
virtual osg : : Vec2Array * getWallTexcoords ( const float height ) const ;
virtual osg : : Vec3Array * getWallNormals ( void ) const {
osg : : ref_ptr < osg : : Vec3Array > nrms = new osg : : Vec3Array ;
const osg : : Vec3Array * vertices = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
for ( unsigned int ipr = 0 ; ipr < getNumPrimitiveSets ( ) ; ipr + + ) {
const osg : : PrimitiveSet * prset = getPrimitiveSet ( ipr ) ;
if ( prset - > getMode ( ) = = osg : : PrimitiveSet : : LINE_LOOP | |
prset - > getMode ( ) = = osg : : PrimitiveSet : : LINE_STRIP ) { // loops and walls
// start with the last point on the loop
osg : : Vec3 prevp = ( * vertices ) [ prset - > index ( prset - > getNumIndices ( ) - 1 ) ] ;
for ( unsigned int i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
osg : : Vec3 nrm = ( curp - prevp ) ^ osg : : Vec3 ( 0 , 0 , 1 ) ;
nrm . normalize ( ) ;
nrms - > push_back ( nrm ) ;
nrms - > push_back ( nrm ) ;
prevp = curp ;
}
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( 0 ) ] ;
osg : : Vec3 nrm = ( curp - prevp ) ^ osg : : Vec3 ( 0 , 0 , 1 ) ;
nrm . normalize ( ) ;
nrms - > push_back ( nrm ) ;
nrms - > push_back ( nrm ) ;
}
}
return nrms . release ( ) ;
}
// geometry creation parameters
void setWallTexrep ( const float w , const float h ) { txxrepWall = w ; txyrepWall = h ; }
/** Wall Geometry will return with this texture applied: */
void setTexture ( const char * tx ) { texture = tx ; }
/** fence/wall height */
void setHeight ( const float h ) { height = h ; }
2005-10-25 21:28:48 +08:00
protected :
2005-10-27 17:37:38 +08:00
float height ;
std : : string texture ;
float txxrepWall , txyrepWall ;
2005-10-25 21:28:48 +08:00
} ;
class ArealConstraint : public osgUtil : : DelaunayConstraint { // forces edges of an area to fit triangles
2005-10-27 17:37:38 +08:00
// areal constraint - general nonuniform field, forest, lake etc.
2005-10-25 21:28:48 +08:00
public :
/** if you derive a class from DelaunayConstraint then you can create
* a specific geometry creation routine .
2005-10-27 17:37:38 +08:00
*/
ArealConstraint ( ) : txxrepArea ( 10 ) , txyrepArea ( 10 ) , txxrepWall ( 10 ) , txyrepWall ( 10 ) { }
/** return a geometry that fills the constraint.
*/
virtual osg : : Geometry * makeAreal ( osg : : Vec3Array * points ) ;
/** or create a wall around the constraint area: */
virtual osg : : Geometry * makeWallGeometry ( osg : : Vec3Array * points ) ;
/** for basic purposes, you can call these routines to make simple fill in geometries */
virtual osg : : DrawArrays * makeWall ( void ) const ;
virtual osg : : Vec3Array * getWall ( const float height ) const ;
virtual osg : : Vec2Array * getWallTexcoords ( const float height ) const ;
virtual osg : : Vec3Array * getWallNormals ( void ) const ;
/** Canopies are the same triangles as the terrain but offset by height above
* ( height might be 0 ) . */
virtual osg : : DrawArrays * makeCanopy ( void ) const ;
virtual osg : : Vec3Array * getCanopy ( const osg : : Vec3Array * points , const float height ) const ;
virtual osg : : Vec2Array * getCanopyTexcoords ( const osg : : Vec3Array * points ) const ;
virtual osg : : Vec3Array * getCanopyNormals ( const osg : : Vec3Array * points ) const ;
// geometry creation parameters
void setTexrep ( const float w , const float h ) { txxrepArea = w ; txyrepArea = h ; }
void setWallTexrep ( const float w , const float h ) { txxrepWall = w ; txyrepWall = h ; }
/** Geometry will return with this texture applied: */
void setWallTexture ( const char * tx ) { walltexture = tx ; }
/** Geometry will return with this texture applied: */
void setTexture ( const char * tx ) { texture = tx ; }
/** fence/wall height */
void setHeight ( const float h ) { height = h ; }
std : : string walltexture ;
2005-10-25 21:28:48 +08:00
protected :
2005-10-27 17:37:38 +08:00
float height ;
std : : string texture ;
float txxrepArea , txyrepArea ;
float txxrepWall , txyrepWall ;
2005-10-25 21:28:48 +08:00
} ;
class LinearConstraint : public osgUtil : : DelaunayConstraint {
/** forces edges of a "road" to fit triangles
* if 2 roads cross , then the overlap will be replaced by a ' cross road '
2005-10-27 17:37:38 +08:00
* and the roads built up to the cross roads with a texture along its length . */
2005-10-25 21:28:48 +08:00
public :
2005-10-27 17:37:38 +08:00
LinearConstraint ( ) : DelaunayConstraint ( ) , txxrepAlong ( 10 ) , txyrepAcross ( 10 ) , width ( 2 ) { }
/** geometry creation parameters */
/* Width of linear feature (eg road, railway) */
void setWidth ( const float w ) { width = w ; }
/** Texture repeat distance across linear (often equal to width) and along its length */
virtual void setTexrep ( const float w , const float h ) { txyrepAcross = h ; txxrepAlong = w ; }
/** generate constant width around line - creates the area to be cut into the terrain. */
virtual void setVertices ( osg : : Vec3Array * lp , const float width ) ;
/** return a geometry that fills the constraint.
*/
virtual osg : : Geometry * makeGeometry ( const osg : : Vec3Array * points ) ;
/** return normals array - flat shaded */
osg : : Vec3Array * getNormals ( const osg : : Vec3Array * points ) ;
/** Roads apply a texture proportional to length along the road line. */
virtual osg : : DrawArrays * makeRoad ( ) const ;
virtual osg : : Vec3Array * getRoadVertices ( ) const ;
virtual osg : : Vec2Array * getRoadTexcoords ( const osg : : Vec3Array * points ) ;
virtual osg : : Vec3Array * getRoadNormals ( const osg : : Vec3Array * points ) const ;
/** Geometry will return with this texture applied: */
void setTexture ( const char * tx ) { texture = tx ; }
2005-10-25 21:28:48 +08:00
protected :
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Vec2Array > _tcoords ;
osg : : ref_ptr < osg : : Vec3Array > _edgecoords ;
float txxrepAlong , txyrepAcross ;
std : : string texture ;
float width ; // width of a linear feature
osg : : ref_ptr < osg : : Vec3Array > _midline ; // defines the midline of a road, rail etc.
2005-10-25 21:28:48 +08:00
} ;
/** a specific type of constaint - that replaces an area with a pyramid */
class pyramid : public osgUtil : : DelaunayConstraint {
/** sample user constriant - creates hole in terrain to fit base of pyramid, and
2005-10-27 17:37:38 +08:00
* geometry of an Egyptian pyramid to fit the hole . */
2005-10-25 21:28:48 +08:00
public :
2005-10-27 17:37:38 +08:00
pyramid ( ) : _side ( 100. ) { }
void setpos ( const osg : : Vec3 p , const float size ) { _pos = p ; _side = size ; }
virtual osg : : Geometry * makeGeometry ( void ) const
{
// create pyramid geometry. Centre plus points around base
const osg : : Vec3Array * _line = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
osg : : Geometry * gm = new osg : : Geometry ;
osg : : Vec3Array * pts = new osg : : Vec3Array ;
osg : : Vec3Array * norms = new osg : : Vec3Array ;
osg : : Vec2Array * tcoords = new osg : : Vec2Array ;
int ip ;
pts - > push_back ( _pos + osg : : Vec3 ( 0 , 0 , _side ) * 0.5 ) ;
for ( ip = 0 ; ip < 4 ; ip + + ) {
pts - > push_back ( ( * _line ) [ ip ] ) ;
}
for ( ip = 1 ; ip < 5 ; ip + + ) {
osg : : Vec3 nrm = ( ( * pts ) [ ip ] - ( * pts ) [ 0 ] ) ^ ( ( * pts ) [ ip = = 4 ? 0 : ip + 1 ] - ( * pts ) [ ip ] ) ;
nrm . normalize ( ) ;
norms - > push_back ( nrm ) ;
}
gm - > setNormalBinding ( osg : : Geometry : : BIND_PER_PRIMITIVE ) ;
gm - > setVertexArray ( pts ) ;
osg : : StateSet * dstate = gm - > getOrCreateStateSet ( ) ;
dstate - > setMode ( GL_LIGHTING , osg : : StateAttribute : : ON ) ;
osg : : Image * image = osgDB : : readImageFile ( " stoneWall.jpg " ) ;
if ( image )
2005-10-25 21:28:48 +08:00
{
2005-10-27 17:37:38 +08:00
osg : : Texture2D * txt = new osg : : Texture2D ;
txt - > setImage ( image ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_S , osg : : Texture2D : : REPEAT ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_T , osg : : Texture2D : : REPEAT ) ;
dstate - > setTextureAttributeAndModes ( 0 , txt , osg : : StateAttribute : : ON ) ;
}
gm - > setNormalArray ( norms ) ;
//// gm->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN,0,6));
osg : : DrawElementsUInt * dui = new osg : : DrawElementsUInt ( GL_TRIANGLES ) ;
for ( ip = 0 ; ip < 4 ; ip + + ) {
dui - > push_back ( 0 ) ;
dui - > push_back ( ip + 1 ) ;
dui - > push_back ( ip = = 3 ? 1 : ip + 2 ) ;
}
tcoords - > push_back ( osg : : Vec2 ( 2 , 4 ) ) ;
tcoords - > push_back ( osg : : Vec2 ( 0 , 0 ) ) ;
tcoords - > push_back ( osg : : Vec2 ( 4 , 0 ) ) ;
tcoords - > push_back ( osg : : Vec2 ( 0 , 0 ) ) ;
tcoords - > push_back ( osg : : Vec2 ( 4 , 0 ) ) ;
gm - > setTexCoordArray ( 0 , tcoords ) ;
gm - > addPrimitiveSet ( dui ) ;
return gm ;
}
virtual void calcVertices ( void ) { // must have a position first
osg : : Vec3Array * edges = new osg : : Vec3Array ;
osg : : Vec3 valong ;
edges - > push_back ( _pos + osg : : Vec3 ( 0.5 , 0.5 , 0 ) * _side ) ;
edges - > push_back ( _pos + osg : : Vec3 ( - 0.5 , 0.5 , 0 ) * _side ) ;
edges - > push_back ( _pos + osg : : Vec3 ( - 0.5 , - 0.5 , 0 ) * _side ) ;
edges - > push_back ( _pos + osg : : Vec3 ( 0.5 , - 0.5 , 0 ) * _side ) ;
setVertexArray ( edges ) ;
}
2005-10-25 21:28:48 +08:00
private :
2005-10-27 17:37:38 +08:00
osg : : Vec3 _pos ; // where the pyramid is
float _side ; // length of side
2005-10-25 21:28:48 +08:00
} ;
float getheight ( const float x , const float y )
{ // returns the x,y,height of terrain
2005-10-27 17:37:38 +08:00
return 150 * sin ( x * .0020 ) * cos ( y * .0020 ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec3d getpt ( const int np )
{ // returns the x,y,height of terrain up to maxp^2 points
2005-10-27 17:37:38 +08:00
static int maxp = 40 ;
int i = np / maxp ;
int j = np % maxp ;
// make the random scale 0.00 if you want an equispaced XY grid.
float x = 3000.0 / ( maxp - 1 ) * i + 0.00052 * rand ( ) ;
float y = 3000.0 / ( maxp - 1 ) * j + 0.0005 * rand ( ) ;
float z = getheight ( x , y ) ;
if ( np > = maxp * maxp ) z = - 1.e32 ;
return osg : : Vec3d ( x , y , z ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Node * createHUD ( const int ndcs , std : : string what )
{ // add a string reporting the type of winding rule tesselation applied
osg : : Geode * geode = new osg : : Geode ( ) ;
std : : string timesFont ( " fonts/arial.ttf " ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
// turn lighting off for the text and disable depth test to ensure its always ontop.
osg : : StateSet * stateset = geode - > getOrCreateStateSet ( ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : OFF ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
// Disable depth test, and make sure that the hud is drawn after everything
// else so that it always appears ontop.
stateset - > setMode ( GL_DEPTH_TEST , osg : : StateAttribute : : OFF ) ;
stateset - > setRenderBinDetails ( 11 , " RenderBin " ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
osg : : Vec3 position ( 50.0f , 900.0f , 0.0f ) ;
osg : : Vec3 delta ( 0.0f , - 35.0f , 0.0f ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
{
osgText : : Text * text = new osgText : : Text ;
geode - > addDrawable ( text ) ;
2005-10-27 17:37:38 +08:00
std : : ostringstream cue ;
cue < < " Delaunay triangulation with constraints level " < < ndcs < < " \n " < < what ;
2005-10-25 21:28:48 +08:00
text - > setFont ( timesFont ) ;
text - > setPosition ( position ) ;
text - > setText ( cue . str ( ) ) ;
text - > setColor ( osg : : Vec4 ( 1.0 , 1.0 , 0.8 , 1.0 ) ) ;
position + = delta * ( ndcs + 2 ) ;
2005-10-27 17:37:38 +08:00
text = new osgText : : Text ;
2005-10-25 21:28:48 +08:00
geode - > addDrawable ( text ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
text - > setFont ( timesFont ) ;
text - > setPosition ( position ) ;
text - > setText ( " (use 'W' wireframe & 'T' texture to visualise mesh) " ) ;
text - > setColor ( osg : : Vec4 ( 1.0 , 1.0 , 0.8 , 1.0 ) ) ;
position + = delta ;
}
{
osgText : : Text * text = new osgText : : Text ;
geode - > addDrawable ( text ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
text - > setFont ( timesFont ) ;
text - > setPosition ( position ) ;
text - > setText ( " Press 'n' to add another constraint. " ) ;
}
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
// create the hud.
osg : : MatrixTransform * modelview_abs = new osg : : MatrixTransform ;
modelview_abs - > setReferenceFrame ( osg : : Transform : : ABSOLUTE_RF ) ;
modelview_abs - > setMatrix ( osg : : Matrix : : identity ( ) ) ;
modelview_abs - > addChild ( geode ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
osg : : Projection * projection = new osg : : Projection ;
projection - > setMatrix ( osg : : Matrix : : ortho2D ( 0 , 1280 , 0 , 1024 ) ) ;
projection - > addChild ( modelview_abs ) ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
return projection ;
2005-10-27 17:37:38 +08:00
2005-10-25 21:28:48 +08:00
}
osg : : Group * makedelaunay ( const int ndcs )
{ // create a terrain tile. This is just an example!
2005-10-27 17:37:38 +08:00
// ndcs is the number of delaunay constraints to be applied
osg : : ref_ptr < osg : : Group > grp = new osg : : Group ;
osg : : ref_ptr < osg : : Geode > geode = new osg : : Geode ;
osg : : ref_ptr < osgUtil : : DelaunayTriangulator > trig = new osgUtil : : DelaunayTriangulator ( ) ;
osg : : StateSet * stateset = geode - > getOrCreateStateSet ( ) ;
osg : : Vec3Array * points = new osg : : Vec3Array ;
osg : : Image * image = osgDB : : readImageFile ( " Lands-Flowers-Small_Purple.png " ) ;
if ( image )
{
osg : : Texture2D * texture = new osg : : Texture2D ;
texture - > setImage ( image ) ;
texture - > setWrap ( osg : : Texture2D : : WRAP_S , osg : : Texture2D : : REPEAT ) ;
texture - > setWrap ( osg : : Texture2D : : WRAP_T , osg : : Texture2D : : REPEAT ) ;
stateset - > setTextureAttributeAndModes ( 0 , texture , osg : : StateAttribute : : ON ) ;
}
geode - > setStateSet ( stateset ) ;
unsigned int i ;
int eod = 0 ;
while ( eod > = 0 ) {
osg : : Vec3d pos = getpt ( eod ) ;
if ( pos . z ( ) > - 10000 ) {
points - > push_back ( pos ) ;
eod + + ;
} else {
eod = - 9999 ;
}
}
std : : vector < pyramid * > pyrlist ;
osg : : ref_ptr < WallConstraint > wc ; // This example does not remove the interior
osg : : ref_ptr < ArealConstraint > dc2 ;
osg : : ref_ptr < ArealConstraint > forest ;
osg : : ref_ptr < LinearConstraint > dc3 ;
osg : : ref_ptr < LinearConstraint > dc6 ;
osg : : ref_ptr < LinearConstraint > dc6a ;
osg : : ref_ptr < LinearConstraint > dc8 ;
osg : : ref_ptr < LinearConstraint > forestroad ;
osg : : ref_ptr < LinearConstraint > forestroad2 ;
osg : : ref_ptr < LinearConstraint > forestroad3 ;
osg : : ref_ptr < osgUtil : : DelaunayConstraint > dc ;
std : : ostringstream what ;
if ( 1 = = 1 ) { // add a simple constraint of few points
osg : : ref_ptr < osgUtil : : DelaunayConstraint > dc = new osgUtil : : DelaunayConstraint ;
osg : : Vec3Array * bounds = new osg : : Vec3Array ;
unsigned int nmax = 4 ;
for ( i = 0 ; i < nmax ; i + + ) {
float x = 910.0 + 800.0 * ( i ) / ( float ) nmax , y = 810.0 + 6000 * ( i - 1 ) * ( i - 1 ) / ( float ) ( nmax * nmax ) ;
bounds - > push_back ( osg : : Vec3 ( x , y , getheight ( x , y ) ) ) ;
}
dc - > setVertexArray ( bounds ) ;
dc - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_STRIP , 0 , nmax ) ) ;
trig - > addInputConstraint ( dc . get ( ) ) ;
what < < nmax < < " point simple constraint \n " ;
}
if ( ndcs > 0 ) { // add 5 pyramids
for ( unsigned int ipy = 0 ; ipy < 5 /*5*/ ; ipy + + ) {
osg : : ref_ptr < pyramid > pyr = new pyramid ;
float x = 2210 + ipy * 120 , y = 1120 + ipy * 220 ;
pyr - > setpos ( osg : : Vec3 ( x , y , getheight ( x , y ) ) , 125.0 + 10 * ipy ) ;
pyr - > calcVertices ( ) ; // make vertices
pyr - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_LOOP , 0 , 4 ) ) ;
trig - > addInputConstraint ( pyr . get ( ) ) ;
pyrlist . push_back ( pyr . get ( ) ) ;
}
what < < 5 < < " pyramids \n " ;
if ( ndcs > 1 ) {
// add a simple constraint feature - this can cut holes in the terrain or just leave the triangles
// with edges forced to the constraint.
dc = new osgUtil : : DelaunayConstraint ;
osg : : Vec3Array * bounds = new osg : : Vec3Array ;
for ( i = 0 ; i < 12 ; i + + ) {
float x = 610.0 + 420 * sin ( i / 3.0 ) , y = 610.0 + 420 * cos ( i / 3.0 ) ;
bounds - > push_back ( osg : : Vec3 ( x , y , getheight ( x , y ) ) ) ;
}
dc - > setVertexArray ( bounds ) ;
dc - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_LOOP , 0 , 12 ) ) ;
trig - > addInputConstraint ( dc . get ( ) ) ;
what < < 12 < < " point closed loop " ;
if ( ndcs > 2 ) {
wc = new WallConstraint ; // This example does not remove the interior
// eg to force terrain edges that are on ridges in the terrain etc.
// use wireframe to see the constrained edges.
// NB this is not necessarily a closed loop of edges.
// we do however build a wall at the coordinates.
bounds = new osg : : Vec3Array ;
for ( i = 0 ; i < 5 ; i + + ) {
float x = 1610.0 + 420 * sin ( i / 1.0 ) , y = 1610.0 + 420 * cos ( i / 1.0 ) ;
bounds - > push_back ( osg : : Vec3 ( x , y , getheight ( x , y ) ) ) ;
}
wc - > setVertexArray ( bounds ) ;
wc - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_STRIP , 0 , 5 ) ) ;
wc - > setHeight ( 12.0 ) ;
trig - > addInputConstraint ( wc . get ( ) ) ;
what < < " with interior removed \n " ;
what < < 5 < < " point wall derived constraint \n " ;
if ( ndcs > 3 ) {
// add a removed area and replace it with a different texture
dc2 = new ArealConstraint ;
bounds = new osg : : Vec3Array ;
for ( i = 0 ; i < 18 ; i + + ) {
float x = 1610.0 + 420 * sin ( i / 3.0 ) , y = 610.0 + 220 * cos ( i / 3.0 ) ;
bounds - > push_back ( osg : : Vec3 ( x , y , getheight ( x , y ) ) ) ;
}
dc2 - > setVertexArray ( bounds ) ;
dc2 - > setTexrep ( 100 , 100 ) ; // texture is repeated at this frequency
dc2 - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_LOOP , 0 , 18 ) ) ;
trig - > addInputConstraint ( dc2 . get ( ) ) ;
what < < 18 < < " point area replaced \n " ;
if ( ndcs > 4 ) {
dc3 = new LinearConstraint ;
// a linear feature or 'road'
osg : : Vec3Array * verts = new osg : : Vec3Array ;
for ( i = 0 ; i < 32 ; i + + ) {
float x = 610.0 + 50 * i + 90 * sin ( i / 5.0 ) , y = 1110.0 + 90 * cos ( i / 5.0 ) ;
verts - > push_back ( osg : : Vec3 ( x , y , getheight ( x , y ) ) ) ;
}
dc3 - > setVertices ( verts , 9.5 ) ; // width of road
for ( osg : : Vec3Array : : iterator vit = points - > begin ( ) ; vit ! = points - > end ( ) ; ) {
if ( dc3 - > contains ( * vit ) ) {
vit = points - > erase ( vit ) ;
} else {
vit + + ;
}
}
trig - > addInputConstraint ( dc3 . get ( ) ) ;
what < < 32 < < " point road constraint \n " ;
if ( ndcs > 5 ) {
// add a removed area and replace it with a 'forest' with textured roof and walls
forest = new ArealConstraint ;
bounds = new osg : : Vec3Array ;
for ( i = 0 ; i < 12 ; i + + ) {
float x = 610.0 + 420 * sin ( i / 2.0 ) , y = 1810.0 + 420 * cos ( i / 2.0 ) ;
bounds - > push_back ( osg : : Vec3 ( x , y , getheight ( x , y ) ) ) ;
}
forest - > setVertexArray ( bounds ) ;
forest - > setHeight ( 50 ) ;
forest - > setWallTexrep ( 100 , 50 ) ;
forest - > setTexrep ( 100 , 100 ) ; // texture is repeated at this frequency
forest - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_LOOP , 0 , 12 ) ) ;
if ( ndcs = = 6 ) trig - > addInputConstraint ( forest . get ( ) ) ;
what < < 12 < < " point forest constraint \n " ;
if ( ndcs > 6 ) { // add roads that intersect forest
osg : : ref_ptr < osgUtil : : DelaunayConstraint > forestplus = new osgUtil : : DelaunayConstraint ;
forestroad = new LinearConstraint ;
verts = new osg : : Vec3Array ;
for ( i = 0 ; i < 12 ; i + + ) {
int ip = ( i - 6 ) * ( i - 6 ) ;
float xp = 410.0 + 20.0 * ip ;
float y = 1210.0 + 150 * i ;
verts - > push_back ( osg : : Vec3 ( xp , y , getheight ( xp , y ) ) ) ;
}
forestroad - > setVertices ( verts , 22 ) ; // add road
forestplus - > merge ( forestroad . get ( ) ) ;
forestroad2 = new LinearConstraint ;
verts = new osg : : Vec3Array ;
for ( i = 0 ; i < 12 ; i + + ) {
int ip = ( i - 6 ) * ( i - 6 ) ;
float xp = 810.0 - 10.0 * ip ;
float y = 1010.0 + 150 * i ;
verts - > push_back ( osg : : Vec3 ( xp , y , getheight ( xp , y ) ) ) ;
}
forestroad2 - > setVertices ( verts , 22 ) ; // add road
forestplus - > merge ( forestroad2 . get ( ) ) ;
forestroad3 = new LinearConstraint ;
verts = new osg : : Vec3Array ;
for ( i = 0 ; i < 6 ; i + + ) {
int ip = ( i - 6 ) * ( i - 6 ) ;
float xp = 210.0 + 140.0 * i + ip * 10.0 ;
float y = 1510.0 + 150 * i ;
verts - > push_back ( osg : : Vec3 ( xp , y , getheight ( xp , y ) ) ) ;
}
forestroad3 - > setVertices ( verts , 22 ) ; // add road
forestplus - > merge ( forestroad3 . get ( ) ) ;
forestplus - > merge ( forest . get ( ) ) ;
forestplus - > handleOverlaps ( ) ;
for ( osg : : Vec3Array : : iterator vit = points - > begin ( ) ; vit ! = points - > end ( ) ; ) {
if ( forestroad - > contains ( * vit ) ) {
vit = points - > erase ( vit ) ;
} else if ( forestroad2 - > contains ( * vit ) ) {
vit = points - > erase ( vit ) ;
} else if ( forestroad3 - > contains ( * vit ) ) {
vit = points - > erase ( vit ) ;
} else {
vit + + ;
}
}
trig - > addInputConstraint ( forestplus . get ( ) ) ;
what < < " roads intersect forest constraint \n " ;
if ( ndcs > 7 ) {
// this option adds a more complex DC
// made of several (ok 2 - extend your own way) overlapping DC's
osg : : ref_ptr < osgUtil : : DelaunayConstraint > dcoverlap = new osgUtil : : DelaunayConstraint ;
float x = 1200 ; float y = 1900 ;
{
verts = new osg : : Vec3Array ;
dc6 = new LinearConstraint ;
verts - > push_back ( osg : : Vec3 ( x - 180 , y , getheight ( x - 180 , y ) ) ) ;
verts - > push_back ( osg : : Vec3 ( x + 180 , y , getheight ( x + 180 , y ) ) ) ;
dc6 - > setVertices ( verts , 22 ) ; // width of road
dcoverlap - > merge ( dc6 . get ( ) ) ;
}
{
dc6a = new LinearConstraint ;
verts = new osg : : Vec3Array ;
verts - > push_back ( osg : : Vec3 ( x , y - 180 , getheight ( x , y - 180 ) ) ) ;
verts - > push_back ( osg : : Vec3 ( x - 20 , y , getheight ( x , y ) ) ) ;
verts - > push_back ( osg : : Vec3 ( x , y + 180 , getheight ( x , y + 180 ) ) ) ;
dc6a - > setVertices ( verts , 22 ) ; // width of road
dcoverlap - > merge ( dc6a . get ( ) ) ;
}
what < < " 2 intersecting roads, with added points \n " ;
if ( ndcs > 9 ) {
// add yet more roads
dc8 = new LinearConstraint ;
verts = new osg : : Vec3Array ;
float rad = 60.0 ;
for ( float theta = 0 ; theta < 4 * osg : : PI ; theta + = 0.1 * osg : : PI ) {
float xp = x + rad * cos ( theta ) , yp = y + rad * sin ( theta ) ;
verts - > push_back ( osg : : Vec3 ( xp , yp , getheight ( xp , yp ) ) ) ;
rad + = 2.5 ;
}
dc8 - > setVertices ( verts , 16 ) ; // width of road
dcoverlap - > merge ( dc8 . get ( ) ) ;
what < < " Spiral road crosses several other constraints. " ;
}
dcoverlap - > handleOverlaps ( ) ;
if ( ndcs > 8 ) {
// remove vertices cleans up the texturing at the intersection.
dcoverlap - > removeVerticesInside ( dc6 . get ( ) ) ;
dcoverlap - > removeVerticesInside ( dc6a . get ( ) ) ;
if ( dc8 . valid ( ) ) dcoverlap - > removeVerticesInside ( dc8 . get ( ) ) ;
what < < " remove internal vertices to improve texturing. " ;
}
for ( osg : : Vec3Array : : iterator vit = points - > begin ( ) ; vit ! = points - > end ( ) ; ) {
if ( dcoverlap - > contains ( * vit ) ) {
vit = points - > erase ( vit ) ;
} else {
vit + + ;
}
}
trig - > addInputConstraint ( dcoverlap . get ( ) ) ;
}
}
}
}
}
}
}
} // ndcs>0
trig - > setInputPointArray ( points ) ;
/** NB you need to supply a vec3 array for the triangulator to calculate normals into */
osg : : Vec3Array * norms = new osg : : Vec3Array ;
trig - > setOutputNormalArray ( norms ) ;
trig - > triangulate ( ) ;
osg : : notify ( osg : : WARN ) < < " End of trig \n " < < std : : endl ;
// Calculate the texture coordinates after triangulation as
//the points may get disordered by the triangulate function
osg : : ref_ptr < osg : : Geometry > gm = new osg : : Geometry ;
gm - > setVertexArray ( points ) ; // points may have been modified in order by triangulation.
/** calculate texture coords for terrain points */
if ( image ) {
float repeat = 150.0 , ry = 150.0 ; // how often to repeat texture
osg : : Vec2Array * tcoords = new osg : : Vec2Array ;
for ( osg : : Vec3Array : : iterator itr = points - > begin ( ) ; itr ! = points - > end ( ) ; itr + + ) {
osg : : Vec2 tcatxy ( ( * itr ) . x ( ) / repeat , ( * itr ) . y ( ) / ry ) ;
tcoords - > push_back ( tcatxy ) ;
}
gm - > setTexCoordArray ( 0 , tcoords ) ;
}
gm - > addPrimitiveSet ( trig - > getTriangles ( ) ) ;
gm - > setNormalArray ( trig - > getOutputNormalArray ( ) ) ;
gm - > setNormalBinding ( osg : : Geometry : : BIND_PER_PRIMITIVE ) ;
geode - > addDrawable ( gm . get ( ) ) ;
if ( ndcs > 0 ) {
for ( std : : vector < pyramid * > : : iterator itr = pyrlist . begin ( ) ; itr ! = pyrlist . end ( ) ; itr + + ) {
trig - > removeInternalTriangles ( * itr ) ;
geode - > addDrawable ( ( * itr ) - > makeGeometry ( ) ) ; // this fills the holes of each pyramid with geometry
}
if ( ndcs > 2 ) {
trig - > removeInternalTriangles ( dc . get ( ) ) ;
wc - > setTexture ( " Brick-Norman-Brown.TGA " ) ; // wall looks like brick
geode - > addDrawable ( wc - > makeWallGeometry ( ) ) ; // this creates wall at wc drawarrays
if ( ndcs > 3 ) {
trig - > removeInternalTriangles ( dc2 . get ( ) ) ;
osg : : ref_ptr < osg : : Vec3Array > arpts = dc2 - > getPoints ( points ) ;
dc2 - > setTexture ( " Lands-Needles_2.png " ) ;
geode - > addDrawable ( dc2 - > makeAreal ( arpts . get ( ) ) ) ; // this creates fill in geometry
if ( ndcs > 4 ) { // a simple "road"
trig - > removeInternalTriangles ( dc3 . get ( ) ) ;
dc3 - > setTexture ( " road.png " ) ;
dc3 - > setTexrep ( 40 , 9.5 ) ; // texture is repeated at this frequency
geode - > addDrawable ( dc3 - > makeGeometry ( points ) ) ; // this creates road geometry
if ( ndcs > 5 ) {
if ( ndcs > 6 ) { // road & forest overlap - order of removal is important
trig - > removeInternalTriangles ( forestroad . get ( ) ) ;
trig - > removeInternalTriangles ( forestroad2 . get ( ) ) ;
trig - > removeInternalTriangles ( forestroad3 . get ( ) ) ;
}
trig - > removeInternalTriangles ( forest . get ( ) ) ;
forest - > setTexture ( " forestRoof.png " ) ;
osg : : ref_ptr < osg : : Vec3Array > locpts = forest - > getPoints ( points ) ;
geode - > addDrawable ( forest - > makeAreal ( locpts . get ( ) ) ) ;
2005-10-25 21:28:48 +08:00
2005-10-27 17:37:38 +08:00
forest - > setWallTexture ( " forestEdge.png " ) ;
geode - > addDrawable ( forest - > makeWallGeometry ( locpts . get ( ) ) ) ;
for ( osg : : Vec3Array : : iterator vit = ( * locpts ) . begin ( ) ; vit ! = ( * locpts ) . end ( ) ; vit + + ) {
( * vit ) + = osg : : Vec3 ( 0 , 0 , 30 ) ;
}
2005-10-25 21:28:48 +08:00
2005-10-27 17:37:38 +08:00
if ( ndcs > 6 ) { // road & forest overlap
forestroad - > setTexture ( " road.png " ) ;
forestroad - > setTexrep ( 40 , 22 ) ; // texture is repeated at this frequency
geode - > addDrawable ( forestroad - > makeGeometry ( points ) ) ; // this creates road geometry
forestroad2 - > setTexture ( " road.png " ) ;
forestroad2 - > setTexrep ( 40 , 22 ) ; // texture is repeated at this frequency
geode - > addDrawable ( forestroad2 - > makeGeometry ( points ) ) ; // this creates road geometry
forestroad3 - > setTexture ( " road.png " ) ;
forestroad3 - > setTexrep ( 40 , 22 ) ; // texture is repeated at this frequency
geode - > addDrawable ( forestroad3 - > makeGeometry ( points ) ) ; // this creates road geometry
if ( ndcs > 7 ) { // several overlapping DC's - add geom
trig - > removeInternalTriangles ( dc6 . get ( ) ) ;
// dc6->makeDrawable();
// dc6a->makeDrawable();
dc6 - > setTexture ( " road.png " ) ;
dc6 - > setTexrep ( 40 , 22 ) ; // texture is repeated at this frequency
geode - > addDrawable ( dc6 - > makeGeometry ( points ) ) ; // this creates road geometry
trig - > removeInternalTriangles ( dc6a . get ( ) ) ;
dc6a - > setTexture ( " road.png " ) ;
dc6a - > setTexrep ( 40 , 22 ) ; // texture is repeated at this frequency
geode - > addDrawable ( dc6a - > makeGeometry ( points ) ) ; // this creates road geometry
if ( dc8 . valid ( ) ) {
trig - > removeInternalTriangles ( dc8 . get ( ) ) ;
dc8 - > setTexture ( " road.png " ) ;
dc8 - > setTexrep ( 40 , 16 ) ; // texture is repeated at this frequency
geode - > addDrawable ( dc8 - > makeGeometry ( points ) ) ; // this creates road geometry
}
}
}
}
}
}
}
}
grp - > addChild ( geode . get ( ) ) ;
2005-10-25 21:28:48 +08:00
grp - > addChild ( createHUD ( ndcs , what . str ( ) ) ) ;
2005-10-27 17:37:38 +08:00
return grp . release ( ) ;
2005-10-25 21:28:48 +08:00
}
class KeyboardEventHandler : public osgGA : : GUIEventHandler
{ // extra event handler traps 'n' key to re-triangulate the basic terrain.
public :
KeyboardEventHandler ( osg : : Node * nd , osgProducer : : Viewer & vr ) :
2005-10-27 17:37:38 +08:00
_scene ( nd ) , viewer ( vr ) , iview ( 0 ) { }
virtual bool handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & )
{
switch ( ea . getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : KEYDOWN ) :
{
if ( _scene & & ea . getKey ( ) = = ' n ' )
{
// re-tesselate the scene graph.
// the same contours are re-tesselated using a new method. Old contours
// & tesselation type are held internally in the derived Geode class tesselateDemoGeometry.
// cxTesselateVisitor tsv;
// _scene->accept(tsv);
iview + + ;
if ( iview > 10 ) iview = 0 ;
osg : : ref_ptr < osg : : Node > loadedModel = makedelaunay ( iview ) ;
viewer . setSceneData ( loadedModel . get ( ) ) ;
return true ;
}
break ;
}
default :
break ;
}
return false ;
}
virtual void accept ( osgGA : : GUIEventHandlerVisitor & v )
{
v . visit ( * this ) ;
}
osg : : Node * _scene ;
osgProducer : : Viewer & viewer ;
int iview ;
2005-10-25 21:28:48 +08:00
} ;
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * WallConstraint : : getWall ( const float height ) const
2005-10-25 21:28:48 +08:00
{ // return array of points for a wall height high around the constraint
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * wall = new osg : : Vec3Array ;
if ( height > 0.0 ) {
osg : : Vec3 off ( 0 , 0 , height ) ;
const osg : : Vec3Array * vertices = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
for ( unsigned int ipr = 0 ; ipr < getNumPrimitiveSets ( ) ; ipr + + ) {
const osg : : PrimitiveSet * prset = getPrimitiveSet ( ipr ) ;
if ( prset - > getMode ( ) = = osg : : PrimitiveSet : : LINE_LOOP | |
prset - > getMode ( ) = = osg : : PrimitiveSet : : LINE_STRIP ) { // nothing else loops
// start with the last point on the loop
for ( unsigned int i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
wall - > push_back ( curp ) ;
wall - > push_back ( curp + off ) ;
}
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( 0 ) ] ;
wall - > push_back ( curp ) ;
wall - > push_back ( curp + off ) ;
}
}
}
return wall ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
osg : : Vec2Array * WallConstraint : : getWallTexcoords ( const float height ) const
2005-10-25 21:28:48 +08:00
{ // return array of points for a wall height high around the constraint
2005-10-27 17:37:38 +08:00
osg : : Vec2Array * tcoords = NULL ;
if ( height > 0.0 ) {
float texrepRound = txxrepWall ;
tcoords = new osg : : Vec2Array ;
float circumference = 0 ; // distance around wall to get exact number of repeats of texture
const osg : : Vec3Array * vertices = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
for ( unsigned int ipr = 0 ; ipr < getNumPrimitiveSets ( ) ; ipr + + ) {
const osg : : PrimitiveSet * prset = getPrimitiveSet ( ipr ) ;
osg : : Vec3 prevp = ( * vertices ) [ prset - > index ( prset - > getNumIndices ( ) - 1 ) ] ;
2005-10-25 21:28:48 +08:00
unsigned int i ;
2005-10-27 17:37:38 +08:00
for ( i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
circumference + = ( curp - prevp ) . length ( ) ;
prevp = curp ;
}
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( 0 ) ] ;
circumference + = ( curp - prevp ) . length ( ) ;
int nround = ( int ) ( circumference / txxrepWall ) ;
if ( nround < 1 ) nround = 1 ; // at least one repeat.
texrepRound = circumference / nround ;
float ds = 0 ;
prevp = ( * vertices ) [ prset - > index ( prset - > getNumIndices ( ) - 1 ) ] ;
if ( tcoords ) {
for ( i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
osg : : Vec2 tci = osg : : Vec2f ( ds / texrepRound , 0 / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
tci = osg : : Vec2f ( ds / texrepRound , height / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
ds + = ( curp - prevp ) . length ( ) ;
prevp = curp ;
}
osg : : Vec2 tci = osg : : Vec2f ( ds / texrepRound , 0 / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
tci = osg : : Vec2f ( ds / texrepRound , height / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
}
} // per primitiveset
}
return tcoords ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
osg : : Geometry * WallConstraint : : makeWallGeometry ( ) const
2005-10-25 21:28:48 +08:00
{
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Geometry > gm = new osg : : Geometry ; // the wall
if ( texture ! = " " ) {
osg : : Image * image = osgDB : : readImageFile ( texture . c_str ( ) ) ;
if ( image )
{
osg : : Texture2D * txt = new osg : : Texture2D ;
osg : : StateSet * stateset = gm - > getOrCreateStateSet ( ) ;
txt - > setImage ( image ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_S , osg : : Texture2D : : REPEAT ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_T , osg : : Texture2D : : CLAMP ) ;
stateset - > setTextureAttributeAndModes ( 0 , txt , osg : : StateAttribute : : ON ) ;
osg : : Material * material = new osg : : Material ;
material - > setAmbient ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4 ( 1.0f , 1.0f , 0.0f , 1.0f ) ) ;
material - > setDiffuse ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
stateset - > setAttribute ( material , osg : : StateAttribute : : ON ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : ON ) ;
}
}
gm - > setVertexArray ( getWall ( height ) ) ;
gm - > addPrimitiveSet ( makeWall ( ) ) ;
gm - > setTexCoordArray ( 0 , getWallTexcoords ( height ) ) ;
gm - > setNormalBinding ( osg : : Geometry : : BIND_PER_VERTEX ) ;
gm - > setNormalArray ( getWallNormals ( ) ) ; // this creates normals to walls
return gm . release ( ) ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * ArealConstraint : : getWallNormals ( ) const
2005-10-25 21:28:48 +08:00
{
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * nrms = new osg : : Vec3Array ;
const osg : : Vec3Array * vertices = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
for ( unsigned int ipr = 0 ; ipr < getNumPrimitiveSets ( ) ; ipr + + ) {
const osg : : PrimitiveSet * prset = getPrimitiveSet ( ipr ) ;
if ( prset - > getMode ( ) = = osg : : PrimitiveSet : : LINE_LOOP ) { // nothing else loops
// start with the last point on the loop
osg : : Vec3 prevp = ( * vertices ) [ prset - > index ( prset - > getNumIndices ( ) - 1 ) ] ;
for ( unsigned int i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
osg : : Vec3 nrm = ( curp - prevp ) ^ osg : : Vec3 ( 0 , 0 , 1 ) ;
nrm . normalize ( ) ;
nrms - > push_back ( nrm ) ;
nrms - > push_back ( nrm ) ;
prevp = curp ;
}
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( 0 ) ] ;
osg : : Vec3 nrm = ( curp - prevp ) ^ osg : : Vec3 ( 0 , 0 , 1 ) ;
nrm . normalize ( ) ;
nrms - > push_back ( nrm ) ;
nrms - > push_back ( nrm ) ;
}
}
return nrms ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * ArealConstraint : : getWall ( const float height ) const
2005-10-25 21:28:48 +08:00
{ // return array of points for a wall height high around the constraint
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * wall = new osg : : Vec3Array ;
if ( height > 0.0 ) {
osg : : Vec3 off ( 0 , 0 , height ) ;
const osg : : Vec3Array * vertices = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
for ( unsigned int ipr = 0 ; ipr < getNumPrimitiveSets ( ) ; ipr + + ) {
const osg : : PrimitiveSet * prset = getPrimitiveSet ( ipr ) ;
if ( prset - > getMode ( ) = = osg : : PrimitiveSet : : LINE_LOOP ) { // nothing else loops
// start with the last point on the loop
for ( unsigned int i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
wall - > push_back ( curp ) ;
wall - > push_back ( curp + off ) ;
}
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( 0 ) ] ;
wall - > push_back ( curp ) ;
wall - > push_back ( curp + off ) ;
}
}
}
return wall ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
osg : : Vec2Array * ArealConstraint : : getWallTexcoords ( const float height ) const
2005-10-25 21:28:48 +08:00
{ // return array of points for a wall height high around the constraint
2005-10-27 17:37:38 +08:00
osg : : Vec2Array * tcoords = NULL ;
if ( height > 0.0 ) {
float texrepRound = txxrepWall ;
tcoords = new osg : : Vec2Array ;
float circumference = 0 ; // distance around wall to get exact number of repeats of texture
const osg : : Vec3Array * vertices = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
for ( unsigned int ipr = 0 ; ipr < getNumPrimitiveSets ( ) ; ipr + + ) {
const osg : : PrimitiveSet * prset = getPrimitiveSet ( ipr ) ;
osg : : Vec3 prevp = ( * vertices ) [ prset - > index ( prset - > getNumIndices ( ) - 1 ) ] ;
2005-10-25 21:28:48 +08:00
unsigned int i ;
2005-10-27 17:37:38 +08:00
for ( i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
circumference + = ( curp - prevp ) . length ( ) ;
prevp = curp ;
}
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( 0 ) ] ;
circumference + = ( curp - prevp ) . length ( ) ;
int nround = ( int ) ( circumference / txxrepWall ) ;
if ( nround < 1 ) nround = 1 ; // at least one repeat.
texrepRound = circumference / nround ;
float ds = 0 ;
prevp = ( * vertices ) [ prset - > index ( prset - > getNumIndices ( ) - 1 ) ] ;
if ( tcoords ) {
for ( i = 0 ; i < prset - > getNumIndices ( ) ; i + + ) {
const osg : : Vec3 curp = ( * vertices ) [ prset - > index ( i ) ] ;
osg : : Vec2 tci = osg : : Vec2f ( ds / texrepRound , 0 / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
tci = osg : : Vec2f ( ds / texrepRound , height / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
ds + = ( curp - prevp ) . length ( ) ;
prevp = curp ;
}
osg : : Vec2 tci = osg : : Vec2f ( ds / texrepRound , 0 / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
tci = osg : : Vec2f ( ds / texrepRound , height / txyrepWall ) ;
tcoords - > push_back ( tci ) ;
}
} // per primitiveset
}
return tcoords ;
2005-10-25 21:28:48 +08:00
}
osg : : DrawArrays * ArealConstraint : : makeCanopy ( void ) const
{
2005-10-27 17:37:38 +08:00
return ( new osg : : DrawArrays ( osg : : PrimitiveSet : : TRIANGLES , 0 , 3 * _interiorTris . size ( ) ) ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec3Array * ArealConstraint : : getCanopy ( const osg : : Vec3Array * points , const float height ) const
{ // returns the array of vertices in the canopy
2005-10-27 17:37:38 +08:00
osg : : Vec3 off ( 0 , 0 , height ) ;
osg : : Vec3Array * internals = new osg : : Vec3Array ;
trilist : : const_iterator tritr ;
for ( tritr = _interiorTris . begin ( ) ; tritr ! = _interiorTris . end ( ) ; tritr + + ) {
for ( int i = 0 ; i < 3 ; i + + ) {
int index = ( * tritr ) [ i ] ;
internals - > push_back ( ( * points ) [ index ] + off ) ;
}
}
return internals ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec3Array * ArealConstraint : : getCanopyNormals ( const osg : : Vec3Array * points ) const
{
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * nrms = new osg : : Vec3Array ;
trilist : : const_iterator tritr ;
for ( tritr = _interiorTris . begin ( ) ; tritr ! = _interiorTris . end ( ) ; tritr + + ) {
osg : : Vec3 e1 = ( * points ) [ ( * tritr ) [ 1 ] ] - ( * points ) [ ( * tritr ) [ 0 ] ] ;
osg : : Vec3 e2 = ( * points ) [ ( * tritr ) [ 2 ] ] - ( * points ) [ ( * tritr ) [ 0 ] ] ;
osg : : Vec3 nrm = e1 ^ e2 ;
nrm . normalize ( ) ;
nrms - > push_back ( nrm ) ;
}
return nrms ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec2Array * ArealConstraint : : getCanopyTexcoords ( const osg : : Vec3Array * points ) const
{
2005-10-27 17:37:38 +08:00
osg : : Vec3Array : : const_iterator tritr ;
osg : : ref_ptr < osg : : Vec2Array > tcoords = new osg : : Vec2Array ;
for ( tritr = points - > begin ( ) ; tritr ! = points - > end ( ) ; tritr + + ) {
// calculate tcoords for terrain from xy drape.
osg : : Vec2 tci = osg : : Vec2f ( tritr - > x ( ) / txxrepArea , tritr - > y ( ) / txyrepArea ) ;
tcoords - > push_back ( tci ) ;
}
return tcoords . release ( ) ;
2005-10-25 21:28:48 +08:00
}
osg : : DrawArrays * ArealConstraint : : makeWall ( void ) const
{ // build a wall height high around the constraint
2005-10-27 17:37:38 +08:00
const osg : : Vec3Array * _line = dynamic_cast < const osg : : Vec3Array * > ( getVertexArray ( ) ) ;
return ( new osg : : DrawArrays ( osg : : PrimitiveSet : : QUAD_STRIP , 0 , 2 + 2 * _line - > size ( ) ) ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Geometry * ArealConstraint : : makeWallGeometry ( osg : : Vec3Array * pt )
{
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Geometry > gm = new osg : : Geometry ; // the wall
osg : : ref_ptr < osg : : Geometry > edges = new osg : : Geometry ; // edges of bounds
edges - > setVertexArray ( pt ) ;
osg : : DrawElementsUInt * trgeom = getTriangles ( ) ;
edges - > addPrimitiveSet ( trgeom ) ;
osg : : ref_ptr < osgUtil : : Tesselator > tscx = new osgUtil : : Tesselator ; // this assembles all the constraints
tscx - > setTesselationType ( osgUtil : : Tesselator : : TESS_TYPE_GEOMETRY ) ;
tscx - > setBoundaryOnly ( true ) ;
tscx - > setWindingType ( osgUtil : : Tesselator : : TESS_WINDING_NONZERO ) ;
// find all edges.
const osg : : Vec3Array * points = dynamic_cast < osg : : Vec3Array * > ( getVertexArray ( ) ) ;
tscx - > retesselatePolygons ( * ( edges ) ) ; // find all edges
if ( walltexture ! = " " ) {
osg : : Image * image = osgDB : : readImageFile ( walltexture . c_str ( ) ) ;
if ( image )
{
osg : : Texture2D * txt = new osg : : Texture2D ;
osg : : StateSet * stateset = gm - > getOrCreateStateSet ( ) ;
txt - > setImage ( image ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_S , osg : : Texture2D : : REPEAT ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_T , osg : : Texture2D : : CLAMP ) ;
stateset - > setTextureAttributeAndModes ( 0 , txt , osg : : StateAttribute : : ON ) ;
}
}
points = dynamic_cast < osg : : Vec3Array * > ( edges - > getVertexArray ( ) ) ;
int nstart = 0 ;
osg : : ref_ptr < osg : : Vec3Array > coords = new osg : : Vec3Array ;
osg : : ref_ptr < osg : : Vec2Array > tcoords = new osg : : Vec2Array ;
for ( unsigned int i = 0 ; i < edges - > getNumPrimitiveSets ( ) ; i + + ) {
osg : : PrimitiveSet * pr = edges - > getPrimitiveSet ( i ) ;
if ( pr - > getMode ( ) = = osg : : PrimitiveSet : : LINE_LOOP ) {
float ds = 0 ;
for ( unsigned int icon = 0 ; icon < pr - > getNumIndices ( ) ; icon + + ) {
unsigned int ithis = pr - > index ( icon ) ;
osg : : Vec3 pt = ( * points ) [ ithis ] ;
coords - > push_back ( pt ) ;
coords - > push_back ( pt + osg : : Vec3 ( 0 , 0 , height ) ) ;
tcoords - > push_back ( osg : : Vec2 ( ds / txxrepWall , 0 ) ) ;
tcoords - > push_back ( osg : : Vec2 ( ds / txxrepWall , 1.0 ) ) ;
if ( icon < pr - > getNumIndices ( ) - 1 ) ds + = ( ( * points ) [ pr - > index ( icon + 1 ) ] - ( * points ) [ ithis ] ) . length ( ) ;
else ds + = ( ( * points ) [ pr - > index ( 0 ) ] - ( * points ) [ ithis ] ) . length ( ) ;
}
// repeat first point
unsigned int ithis = pr - > index ( 0 ) ;
coords - > push_back ( ( * points ) [ ithis ] ) ;
coords - > push_back ( ( * points ) [ ithis ] + osg : : Vec3 ( 0 , 0 , height ) ) ;
tcoords - > push_back ( osg : : Vec2 ( ds / txxrepWall , 0 ) ) ;
tcoords - > push_back ( osg : : Vec2 ( ds / txxrepWall , 1.0 ) ) ;
gm - > setVertexArray ( coords . get ( ) ) ;
gm - > setTexCoordArray ( 0 , tcoords . get ( ) ) ;
gm - > addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : QUAD_STRIP , nstart , 2 + 2 * pr - > getNumIndices ( ) ) ) ;
nstart + = 2 + 2 * pr - > getNumIndices ( ) ;
}
}
return gm . release ( ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Geometry * ArealConstraint : : makeAreal ( osg : : Vec3Array * points )
{
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Geometry > gm ; // the fill in area
if ( _interiorTris . size ( ) > 0 ) {
gm = new osg : : Geometry ; // the forest roof
gm - > setVertexArray ( points ) ;
osg : : DrawElementsUInt * trgeom = getTriangles ( ) ;
gm - > addPrimitiveSet ( trgeom ) ;
gm - > setNormalArray ( getCanopyNormals ( points ) ) ;
gm - > setNormalBinding ( osg : : Geometry : : BIND_PER_PRIMITIVE ) ;
gm - > setTexCoordArray ( 0 , getCanopyTexcoords ( points ) ) ;
osg : : Image * image = osgDB : : readImageFile ( texture ) ;
if ( image )
{
osg : : Texture2D * txt = new osg : : Texture2D ;
osg : : StateSet * stateset = gm - > getOrCreateStateSet ( ) ;
txt - > setImage ( image ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_S , osg : : Texture2D : : REPEAT ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_T , osg : : Texture2D : : REPEAT ) ;
stateset - > setTextureAttributeAndModes ( 0 , txt , osg : : StateAttribute : : ON ) ;
osg : : Material * material = new osg : : Material ;
material - > setAmbient ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
material - > setDiffuse ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
stateset - > setAttribute ( material , osg : : StateAttribute : : ON ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : ON ) ;
}
}
return gm . release ( ) ;
2005-10-25 21:28:48 +08:00
}
void LinearConstraint : : setVertices ( osg : : Vec3Array * lp , const float w )
{ // generate constant width around line (calls setvertices(edges))
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Vec3Array > edges = new osg : : Vec3Array ;
_tcoords = new osg : : Vec2Array ; // texture coordinates for replacement geometry
_edgecoords = new osg : : Vec3Array ; // posiiton coordinates for replacement geometry
width = w ;
_midline = lp ;
float ds = 0 ;
for ( unsigned int i = 0 ; i < lp - > size ( ) ; i + + ) {
osg : : Vec3 valong ;
osg : : Vec3 pos [ 2 ] ;
if ( i = = 0 ) {
valong = ( * lp ) [ i + 1 ] - ( * lp ) [ i ] ;
} else if ( i = = lp - > size ( ) - 1 ) {
valong = ( * lp ) [ i ] - ( * lp ) [ i - 1 ] ;
} else {
valong = ( * lp ) [ i + 1 ] - ( * lp ) [ i - 1 ] ;
}
valong . normalize ( ) ;
osg : : Vec3 vperp = valong ^ osg : : Vec3 ( 0 , 0 , 1 ) ;
pos [ 0 ] = ( * lp ) [ i ] - vperp * .5 * width ;
pos [ 1 ] = ( * lp ) [ i ] + vperp * .5 * width ;
edges - > push_back ( pos [ 0 ] ) ;
_edgecoords - > push_back ( pos [ 0 ] ) ;
_tcoords - > push_back ( osg : : Vec2 ( 0 / txyrepAcross , ds / txxrepAlong ) ) ;
edges - > insert ( edges - > begin ( ) , pos [ 1 ] ) ;
_edgecoords - > insert ( _edgecoords - > begin ( ) , pos [ 1 ] ) ;
_tcoords - > insert ( _tcoords - > begin ( ) , osg : : Vec2 ( width / txyrepAcross , ds / txxrepAlong ) ) ;
if ( i < lp - > size ( ) - 1 ) ds + = ( ( * lp ) [ i + 1 ] - ( * lp ) [ i ] ) . length ( ) ;
}
setVertexArray ( edges . get ( ) ) ;
addPrimitiveSet ( new osg : : DrawArrays ( osg : : PrimitiveSet : : LINE_LOOP , 0 , edges - > size ( ) ) ) ;
2005-10-25 21:28:48 +08:00
}
osg : : DrawArrays * LinearConstraint : : makeRoad ( void ) const
{
2005-10-27 17:37:38 +08:00
return new osg : : DrawArrays ( osg : : PrimitiveSet : : QUAD_STRIP , 0 , 2 * _midline - > size ( ) ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec3Array * LinearConstraint : : getRoadNormals ( const osg : : Vec3Array * points ) const
{
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * nrms = new osg : : Vec3Array ;
for ( unsigned int i = 0 ; i < _midline - > size ( ) ; i + + ) {
osg : : Vec3 valong ; // vector along midline of road
if ( i = = 0 ) {
valong = ( * _midline ) [ i + 1 ] - ( * _midline ) [ i ] ;
} else if ( i = = _midline - > size ( ) - 1 ) {
valong = ( * _midline ) [ i ] - ( * _midline ) [ i - 1 ] ;
} else {
valong = ( * _midline ) [ i + 1 ] - ( * _midline ) [ i - 1 ] ;
}
osg : : Vec3 vperp = valong ^ osg : : Vec3 ( 0 , 0 , 1 ) ;
osg : : Vec3 nrm = vperp ^ valong ; // normal to linear
nrm . normalize ( ) ;
nrms - > push_back ( nrm ) ; // repeated for each vertex of linear.
nrms - > push_back ( nrm ) ;
}
return nrms ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * LinearConstraint : : getRoadVertices ( ) const
2005-10-25 21:28:48 +08:00
{
2005-10-27 17:37:38 +08:00
osg : : Vec3Array * linearEdges = new osg : : Vec3Array ;
for ( unsigned int i = 0 ; i < _midline - > size ( ) ; i + + ) {
osg : : Vec3 valong ; // vector along midline of road
if ( i = = 0 ) {
valong = ( * _midline ) [ i + 1 ] - ( * _midline ) [ i ] ;
} else if ( i = = _midline - > size ( ) - 1 ) {
valong = ( * _midline ) [ i ] - ( * _midline ) [ i - 1 ] ;
} else {
valong = ( * _midline ) [ i + 1 ] - ( * _midline ) [ i - 1 ] ;
}
valong . normalize ( ) ;
osg : : Vec3 vperp = valong ^ osg : : Vec3 ( 0 , 0 , 1 ) ; // vector across road
// sides of linear
linearEdges - > push_back ( ( * _midline ) [ i ] - vperp * .5 * width ) ;
linearEdges - > push_back ( ( * _midline ) [ i ] + vperp * .5 * width ) ;
}
return linearEdges ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec2Array * LinearConstraint : : getRoadTexcoords ( const osg : : Vec3Array * points ) {
2005-10-27 17:37:38 +08:00
// need to create a vec2 array from the coordinates that fits the road
osg : : Vec3Array : : const_iterator tritr ;
osg : : ref_ptr < osg : : Vec2Array > tcoords = new osg : : Vec2Array ;
for ( tritr = points - > begin ( ) ; tritr ! = points - > end ( ) ; tritr + + ) {
osg : : Vec2 tci ( - 1. , - 1. ) ;
int ib = 0 ;
// osg::Vec3Array *varr=dynamic_cast<osg::Vec3Array*>(getVertexArray());
bool ptfound = false ;
for ( osg : : Vec3Array : : iterator vit = _edgecoords - > begin ( ) ; vit ! = _edgecoords - > end ( ) & & ! ptfound ; vit + + ) {
if ( ( * vit ) = = ( * tritr ) ) {
tci = _tcoords - > at ( ib ) ;
ptfound = true ;
}
ib + + ;
}
if ( ! ptfound ) { // search for surrounding points and interpolate
ib = 0 ;
osg : : Vec3 pminus = ( _edgecoords - > back ( ) ) ; // need pminus for interpolation
int ibm1 = _edgecoords - > size ( ) - 1 ;
for ( osg : : Vec3Array : : iterator vit = _edgecoords - > begin ( ) ; vit ! = _edgecoords - > end ( ) /*&& !ptfound*/ ; vit + + ) {
osg : : Vec3 pplus = ( * vit ) - ( * tritr ) ;
osg : : Vec3 dpm = pminus - ( * tritr ) ;
pplus . set ( pplus . x ( ) , pplus . y ( ) , 0 ) ;
dpm . set ( dpm . x ( ) , dpm . y ( ) , 0 ) ;
float dprod = pplus * dpm / ( pplus . length ( ) * dpm . length ( ) ) ;
if ( dprod < - 0.9999 ) { // *tritr lies between....
osg : : Vec2 tminus = _tcoords - > at ( ibm1 ) ;
osg : : Vec2 tplus = _tcoords - > at ( ib ) ;
float frac = ( dpm . length ( ) / ( dpm . length ( ) + pplus . length ( ) ) ) ;
tci = tminus + ( ( tplus - tminus ) * frac ) ;
ptfound = true ;
}
ibm1 = ib ;
ib + + ;
pminus = ( * vit ) ;
}
}
tcoords - > push_back ( tci ) ;
}
// some extra points are not interpolated as they lie between 2 interpolated vertices
for ( tritr = points - > begin ( ) ; tritr ! = points - > end ( ) ; tritr + + ) {
int ib = tritr - points - > begin ( ) ;
osg : : Vec2 tci = tcoords - > at ( ib ) ;
if ( tci . x ( ) < - .99 & & tci . y ( ) < - .99 ) {
// search through each of the primitivesets
osg : : Vec3Array : : const_iterator ptitr ;
// osg::notify(osg::WARN) << "Not calculated " << (*tritr).x() <<"," << (*tritr).y() << std::endl;
for ( ptitr = points - > begin ( ) ; ptitr ! = points - > end ( ) ; ptitr + + ) {
}
}
}
return tcoords . release ( ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Vec3Array * LinearConstraint : : getNormals ( const osg : : Vec3Array * points )
{
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Vec3Array > norms = new osg : : Vec3Array ;
for ( osg : : DrawElementsUInt : : iterator uiitr = prim_tris_ - > begin ( ) ; uiitr ! = prim_tris_ - > end ( ) ; uiitr + = 3 ) {
osg : : Vec3 e1 = ( * points ) [ * ( uiitr + 1 ) ] - ( * points ) [ ( * uiitr ) ] ;
osg : : Vec3 e2 = ( * points ) [ * ( uiitr + 2 ) ] - ( * points ) [ * ( uiitr + 1 ) ] ;
osg : : Vec3 n = e1 ^ e2 ;
n . normalize ( ) ;
// if (n.z()<0) n=-n;
norms - > push_back ( n ) ;
}
return norms . release ( ) ;
2005-10-25 21:28:48 +08:00
}
osg : : Geometry * LinearConstraint : : makeGeometry ( const osg : : Vec3Array * points )
{
2005-10-27 17:37:38 +08:00
osg : : ref_ptr < osg : : Geometry > gm = new osg : : Geometry ; // the fill in road/railway
if ( _midline - > size ( ) > 0 ) {
osg : : ref_ptr < osg : : Vec3Array > locpts = getPoints ( points ) ;
if ( texture ! = " " ) {
osg : : Image * image = osgDB : : readImageFile ( texture . c_str ( ) ) ;
if ( image )
{
osg : : Texture2D * txt = new osg : : Texture2D ;
osg : : StateSet * stateset = gm - > getOrCreateStateSet ( ) ;
txt - > setImage ( image ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_S , osg : : Texture2D : : REPEAT ) ;
txt - > setWrap ( osg : : Texture2D : : WRAP_T , osg : : Texture2D : : REPEAT ) ;
stateset - > setTextureAttributeAndModes ( 0 , txt , osg : : StateAttribute : : ON ) ;
osg : : Material * material = new osg : : Material ;
material - > setAmbient ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
material - > setDiffuse ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
stateset - > setAttribute ( material , osg : : StateAttribute : : ON ) ;
stateset - > setMode ( GL_LIGHTING , osg : : StateAttribute : : ON ) ;
}
gm - > setTexCoordArray ( 0 , getRoadTexcoords ( locpts . get ( ) ) ) ;
}
gm - > setVertexArray ( locpts . get ( ) ) ;
gm - > setNormalArray ( getNormals ( locpts . get ( ) ) ) ;
gm - > setNormalBinding ( osg : : Geometry : : BIND_PER_PRIMITIVE ) ;
gm - > addPrimitiveSet ( getTriangles ( ) ) ;
}
return gm . release ( ) ;
2005-10-25 21:28:48 +08:00
}
2005-10-27 17:37:38 +08:00
2005-11-03 18:16:38 +08:00
int main ( int argc , char * * argv )
{
// use an ArgumentParser object to manage the program arguments.
osg : : ArgumentParser arguments ( & argc , argv ) ;
// set up the usage document, in case we need to print out how to use this program.
arguments . getApplicationUsage ( ) - > setApplicationName ( arguments . getApplicationName ( ) ) ;
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " is the standard OpenSceneGraph example which loads and visualises 3d models. " ) ;
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] filename ... " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --image <filename> " , " Load an image and render it on a quad " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --dem <filename> " , " Load an image/DEM and render it on a HeightField " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display command line paramters " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --help-env " , " Display environmental variables available " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --help-keys " , " Display keyboard & mouse bindings available " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --help-all " , " Display all command line, env vars and keyboard & mouse bindigs. " ) ;
// construct the viewer.
osgProducer : : Viewer viewer ( arguments ) ;
// set up the value with sensible default event handlers.
viewer . setUpViewer ( osgProducer : : Viewer : : STANDARD_SETTINGS ) ;
// get details on keyboard and mouse bindings used by the viewer.
viewer . getUsage ( * arguments . getApplicationUsage ( ) ) ;
// if user request help write it out to cout.
bool helpAll = arguments . read ( " --help-all " ) ;
unsigned int helpType = ( ( helpAll | | arguments . read ( " -h " ) | | arguments . read ( " --help " ) ) ? osg : : ApplicationUsage : : COMMAND_LINE_OPTION : 0 ) |
( ( helpAll | | arguments . read ( " --help-env " ) ) ? osg : : ApplicationUsage : : ENVIRONMENTAL_VARIABLE : 0 ) |
( ( helpAll | | arguments . read ( " --help-keys " ) ) ? osg : : ApplicationUsage : : KEYBOARD_MOUSE_BINDING : 0 ) ;
if ( helpType )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout , helpType ) ;
return 1 ;
}
// report any errors if they have occured when parsing the program aguments.
if ( arguments . errors ( ) )
{
arguments . writeErrorMessages ( std : : cout ) ;
return 1 ;
}
if ( arguments . argc ( ) < 1 )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout , osg : : ApplicationUsage : : COMMAND_LINE_OPTION ) ;
return 1 ;
}
osg : : Timer_t start_tick = osg : : Timer : : instance ( ) - > tick ( ) ;
// create the scene from internal specified terrain/constraints.
osg : : ref_ptr < osg : : Node > loadedModel = makedelaunay ( 0 ) ;
// if no model has been successfully loaded report failure.
if ( ! loadedModel )
{
std : : cout < < arguments . getApplicationName ( ) < < " : No data loaded " < < std : : endl ;
return 1 ;
}
// any option left unread are converted into errors to write out later.
arguments . reportRemainingOptionsAsUnrecognized ( ) ;
// report any errors if they have occured when parsing the program aguments.
if ( arguments . errors ( ) )
{
arguments . writeErrorMessages ( std : : cout ) ;
}
osg : : Timer_t end_tick = osg : : Timer : : instance ( ) - > tick ( ) ;
std : : cout < < " Time to load = " < < osg : : Timer : : instance ( ) - > delta_s ( start_tick , end_tick ) < < std : : endl ;
// optimize the scene graph, remove rendundent nodes and state etc.
osgUtil : : Optimizer optimizer ;
optimizer . optimize ( loadedModel . get ( ) ) ;
// pass the loaded scene graph to the viewer.
viewer . setSceneData ( loadedModel . get ( ) ) ;
// copied from osgtessealte.cpp
// add event handler for keyboard 'n' to retriangulate
viewer . getEventHandlerList ( ) . push_front ( new KeyboardEventHandler ( loadedModel . get ( ) , viewer ) ) ;
// create the windows and run the threads.
viewer . realize ( ) ;
while ( ! viewer . done ( ) )
{
// wait for all cull and draw threads to complete.
viewer . sync ( ) ;
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer . update ( ) ;
// fire off the cull and draw traversals of the scene.
viewer . frame ( ) ;
}
// wait for all cull and draw threads to complete before exit.
viewer . sync ( ) ;
return 0 ;
}