From b9f032bbb51204edc5e2f7cb2a0890339eeb330b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 18 Jan 2004 21:59:20 +0000 Subject: [PATCH] Updates for improvements to osgdem, such as adding support for skirt and border into osg::HeightField, handling of computation of neigherbouring tiles in osgdem's DestinationGraph. --- examples/osgdem/DataSet.cpp | 130 +++++++++++++++++++++++++++++++++-- examples/osgdem/DataSet.h | 31 +++++++++ include/osg/Shape | 56 +++++++++++---- include/osg/Vec3 | 5 ++ src/osg/ShapeDrawable.cpp | 106 ++++++++++++++++++++++++++-- src/osgPlugins/osg/Shape.cpp | 20 ++++++ 6 files changed, 327 insertions(+), 21 deletions(-) diff --git a/examples/osgdem/DataSet.cpp b/examples/osgdem/DataSet.cpp index 93893cdec..b3800fa6e 100644 --- a/examples/osgdem/DataSet.cpp +++ b/examples/osgdem/DataSet.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -772,6 +773,7 @@ void DataSet::Source::buildOverviews() DataSet::DestinationTile::DestinationTile(): + _dataSet(0), _imagery_maxNumColumns(4096), _imagery_maxNumRows(4096), _imagery_maxSourceResolutionX(0.0f), @@ -918,6 +920,17 @@ void DataSet::DestinationTile::allocate() } +void DataSet::DestinationTile::computeNeighboursFromQuadMap() +{ + if (_dataSet) + { + setNeighbours(_dataSet->getTile(_level,_X-1,_Y),_dataSet->getTile(_level,_X-1,_Y-1), + _dataSet->getTile(_level,_X,_Y-1),_dataSet->getTile(_level,_X+1,_Y-1), + _dataSet->getTile(_level,_X+1,_Y),_dataSet->getTile(_level,_X+1,_Y+1), + _dataSet->getTile(_level,_X,_Y+1),_dataSet->getTile(_level,_X-1,_Y+1)); + } +} + void DataSet::DestinationTile::setNeighbours(DestinationTile* left, DestinationTile* left_below, DestinationTile* below, DestinationTile* below_right, DestinationTile* right, DestinationTile* right_above, @@ -1302,8 +1315,12 @@ osg::Node* DataSet::DestinationTile::createScene() { if (_terrain.valid() && _terrain->_heightField.valid()) { + osg::HeightField* hf = _terrain->_heightField.get(); + + hf->setSkirtHeight(0.003f); + osg::Geode* geode = new osg::Geode; - geode->addDrawable(new osg::ShapeDrawable(_terrain->_heightField.get())); + geode->addDrawable(new osg::ShapeDrawable(hf)); if (_imagery.valid() && _imagery->_image.valid()) { @@ -1319,6 +1336,89 @@ osg::Node* DataSet::DestinationTile::createScene() stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } + // create the skirt. + if (false) + { + + osg::Vec3 skirtVector(0.0f,0.0f,-0.003f); + + int numColumns = hf->getNumColumns(); + int numRows = hf->getNumRows(); + + int numVerticesInSkirt = 2*(numColumns*2 + numRows*2 - 3); + + osg::Geometry* skirt = new osg::Geometry; + osg::Vec3Array& v = *(new osg::Vec3Array(numVerticesInSkirt)); + osg::Vec3Array& n = *(new osg::Vec3Array(numVerticesInSkirt)); + osg::Vec2Array& t = *(new osg::Vec2Array(numVerticesInSkirt)); + + osg::DrawArrays& skirtDrawArrays = *(new osg::DrawArrays(GL_QUAD_STRIP,0,numVerticesInSkirt)); + int vi=0; + int r,c; + // create bottom skirt vertices + r=0; + float dt_dx = 1.0f/(float)(numColumns-1); + float dt_dy = 1.0f/(float)(numRows-1); + for(c=0;cgetVertex(c,r); + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + + v[vi] = hf->getVertex(c,r)+skirtVector; + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + + } + // create right skirt vertices + c=numColumns-1; + for(r=0;rgetVertex(c,r); + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + + v[vi] = hf->getVertex(c,r)+skirtVector; + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + } + // create top skirt vertices + r=numRows-1; + for(c=numColumns-1;c>0;--c) + { + v[vi] = hf->getVertex(c,r); + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + + v[vi] = hf->getVertex(c,r)+skirtVector; + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + } + // create left skirt vertices + c=0; + for(r=numRows-1;r>=0;--r) + { + v[vi] = hf->getVertex(c,r); + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + + v[vi] = hf->getVertex(c,r)+skirtVector; + n[vi] = hf->getNormal(c,r); + t[vi++] = osg::Vec2(c*dt_dx,r*dt_dy); + } + + // pass arrays to Geometry + skirt->setVertexArray(&v); + skirt->setNormalArray(&n); + skirt->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + skirt->setTexCoordArray(0,&t); + + skirt->addPrimitiveSet(&skirtDrawArrays); + + geode->addDrawable(skirt); + + } + return geode; } else @@ -1375,6 +1475,24 @@ void DataSet::DestinationTile::addRequiredResolutions(CompositeSource* sourceGra } } +void DataSet::CompositeDestination::computeNeighboursFromQuadMap() +{ + // handle leaves + for(TileList::iterator titr=_tiles.begin(); + titr!=_tiles.end(); + ++titr) + { + (*titr)->computeNeighboursFromQuadMap(); + } + + // handle chilren + for(ChildList::iterator citr=_children.begin(); + citr!=_children.end(); + ++citr) + { + (*citr)->computeNeighboursFromQuadMap(); + } +} void DataSet::CompositeDestination::addRequiredResolutions(CompositeSource* sourceGraph) { @@ -1617,6 +1735,7 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(osgTerrain::Coord DestinationTile* tile = new DestinationTile; tile->_name = os.str(); + tile->_dataSet = this; tile->_cs = cs; tile->_extents = extents; tile->_level = currentLevel; @@ -1627,6 +1746,8 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(osgTerrain::Coord tile->computeMaximumSourceResolution(_sourceGraph.get()); tile->allocate(); + insertTileToQuadMap(tile); + if (currentLevel>=maxNumLevels-1) { // bottom level can't divide any further. @@ -1801,9 +1922,8 @@ void DataSet::computeDestinationGraphFromSources(unsigned int numLevels) 0, numLevels); - - - + // now traverse the destination graph to build neighbours. + _destinationGraph->computeNeighboursFromQuadMap(); } @@ -1913,7 +2033,7 @@ void DataSet::updateSourcesForDestinationGraphNeeds() for(CompositeSource::source_iterator itr(_sourceGraph.get());itr.valid();++itr) { Source* source = itr->get(); - //source->buildOverviews(); + source->buildOverviews(); } } diff --git a/examples/osgdem/DataSet.h b/examples/osgdem/DataSet.h index 2dab1869a..ff3b63756 100644 --- a/examples/osgdem/DataSet.h +++ b/examples/osgdem/DataSet.h @@ -633,6 +633,8 @@ class DataSet : public osg::Referenced DestinationTile(); + + void computeNeighboursFromQuadMap(); void setNeighbours(DestinationTile* left, DestinationTile* left_below, DestinationTile* below, DestinationTile* below_right, @@ -675,6 +677,8 @@ class DataSet : public osg::Referenced std::string _name; + DataSet* _dataSet; + osg::ref_ptr _imagery; osg::ref_ptr _terrain; osg::ref_ptr _models; @@ -712,6 +716,8 @@ class DataSet : public osg::Referenced _type(GROUP), _maxVisibleDistance(FLT_MAX) {} + void computeNeighboursFromQuadMap(); + void addRequiredResolutions(CompositeSource* sourceGraph); void readFrom(CompositeSource* sourceGraph); @@ -730,6 +736,29 @@ class DataSet : public osg::Referenced }; + + typedef std::map Column; + typedef std::map Level; + typedef std::map QuadMap; + + void insertTileToQuadMap(DestinationTile* tile) + { + _quadMap[tile->_level][tile->_X][tile->_Y] = tile; + } + + DestinationTile* getTile(unsigned int level,unsigned int X, unsigned int Y) + { + QuadMap::iterator levelItr = _quadMap.find(level); + if (levelItr==_quadMap.end()) return 0; + + Level::iterator columnItr = levelItr->second.find(X); + if (columnItr==levelItr->second.end()) return 0; + + Column::iterator rowItr = columnItr->second.find(Y); + if (rowItr==columnItr->second.end()) return 0; + else return rowItr->second; + } + public: @@ -777,6 +806,8 @@ class DataSet : public osg::Referenced osg::ref_ptr _sourceGraph; osg::ref_ptr _destinationGraph; + + QuadMap _quadMap; osg::ref_ptr _coordinateSystem; osg::Matrixd _geoTransform; diff --git a/include/osg/Shape b/include/osg/Shape index 34b65fb35..4bd58f5fa 100644 --- a/include/osg/Shape +++ b/include/osg/Shape @@ -423,7 +423,9 @@ class SG_EXPORT HeightField : public Shape _rows(0), _origin(0.0f,0.0f,0.0f), _dx(1.0f), - _dy(1.0f) {} + _dy(1.0f), + _skirtHeight(0.0f), + _borderWidth(0) {} HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(mesh,copyop), @@ -432,6 +434,8 @@ class SG_EXPORT HeightField : public Shape _origin(mesh._origin), _dx(mesh._dx), _dy(mesh._dy), + _skirtHeight(mesh._skirtHeight), + _borderWidth(mesh._borderWidth), _heights(mesh._heights) {} META_Shape(osg, HeightField) @@ -455,6 +459,28 @@ class SG_EXPORT HeightField : public Shape inline void setYInterval(float dy) { _dy = dy; } inline float getYInterval() const { return _dy; } + + /** Set the height of the skirt to render around the edge of HeightField. + * The skirt is used as a means of disguising edge boundaries between adjacent HeightField, particular + * of ones with different resolutions.*/ + void setSkirtHeight(float skirtHeight) { _skirtHeight = skirtHeight; } + + /** Get the height of the skirt to render around the edge of HeightField.*/ + float getSkirtHeight() const { return _skirtHeight; } + + /** Set the width in number of cells in from the edge that the height field should be rendered from. + * This exists to allow gradient and curvature continutity to be maintained between adjacent HeightField, where + * the border cells will overlap adjacent HeightField.*/ + void setBorderWidth(unsigned int borderWidth) { _borderWidth = borderWidth; } + + /** Get the width in number of cells in from the edge that the height field should be rendered from.*/ + unsigned int getBorderWidth() const { return _borderWidth; } + + inline void setRotation(const Quat& quat) { _rotation = quat; } + inline const Quat& getRotation() const { return _rotation; } + inline Matrix getRotationMatrix() const { return Matrix(_rotation); } + inline bool zeroRotation() const { return _rotation.zeroRotation(); } + inline void setHeight(unsigned int c,unsigned int r,float value) { @@ -474,25 +500,31 @@ class SG_EXPORT HeightField : public Shape HeightList& getHeightList() { return _heights; } const HeightList& getHeightList() const { return _heights; } + inline Vec3 getVertex(unsigned int c,unsigned int r) const + { + return Vec3(_origin.x()+getXInterval()*(float)c, + _origin.y()+getYInterval()*(float)r, + _origin.z()+_heights[c+r*_columns]); + } + Vec3 getNormal(unsigned int c,unsigned int r) const; - - inline void setRotation(const Quat& quat) { _rotation = quat; } - inline const Quat& getRotation() const { return _rotation; } - inline Matrix getRotationMatrix() const { return Matrix(_rotation); } - inline bool zeroRotation() const { return _rotation.zeroRotation(); } protected: ~HeightField() {} - unsigned int _columns,_rows; + unsigned int _columns,_rows; - osg::Vec3 _origin; - float _dx; - float _dy; + osg::Vec3 _origin; + float _dx; + float _dy; - Quat _rotation; - HeightList _heights; + float _skirtHeight; + unsigned int _borderWidth; + + Quat _rotation; + HeightList _heights; + }; typedef HeightField Grid; diff --git a/include/osg/Vec3 b/include/osg/Vec3 index f36d85829..6d6701b9f 100644 --- a/include/osg/Vec3 +++ b/include/osg/Vec3 @@ -56,6 +56,11 @@ class Vec3 _v[0]=x; _v[1]=y; _v[2]=z; } + inline void set( const Vec3& rhs) + { + _v[0]=rhs._v[0]; _v[1]=rhs._v[1]; _v[2]=rhs._v[2]; + } + inline float& operator [] (int i) { return _v[i]; } inline float operator [] (int i) const { return _v[i]; } diff --git a/src/osg/ShapeDrawable.cpp b/src/osg/ShapeDrawable.cpp index 840b0cd71..51706f3d4 100644 --- a/src/osg/ShapeDrawable.cpp +++ b/src/osg/ShapeDrawable.cpp @@ -564,6 +564,7 @@ void DrawShapeVisitor::apply(const HeightField& field) glPushMatrix(); glTranslatef(field.getOrigin().x(),field.getOrigin().y(),field.getOrigin().z()); + if (!field.zeroRotation()) { @@ -578,21 +579,102 @@ void DrawShapeVisitor::apply(const HeightField& field) float dv = 1.0f/((float)field.getNumRows()-1.0f); float vBase = 0.0f; + + Vec3 vertTop; + Vec3 normTop; + + Vec3 vertBase; + Vec3 normBase; + + if (field.getSkirtHeight()!=0.0f) + { + glBegin(GL_QUAD_STRIP); + + float u = 0.0f; + + // draw bottom skirt + unsigned int col; + vertTop.y() = 0.0f; + for(col=0;col