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.
This commit is contained in:
Robert Osfield 2004-01-18 21:59:20 +00:00
parent c06c73993e
commit b9f032bbb5
6 changed files with 327 additions and 21 deletions

View File

@ -17,6 +17,7 @@
#include <osg/ShapeDrawable>
#include <osg/Texture2D>
#include <osg/Group>
#include <osg/Geometry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
@ -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;c<numColumns-1;++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 right skirt vertices
c=numColumns-1;
for(r=0;r<numRows-1;++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);
}
// 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();
}
}

View File

@ -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<DestinationData> _imagery;
osg::ref_ptr<DestinationData> _terrain;
osg::ref_ptr<DestinationData> _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<unsigned int,DestinationTile*> Column;
typedef std::map<unsigned int,Column> Level;
typedef std::map<unsigned int,Level> 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<CompositeSource> _sourceGraph;
osg::ref_ptr<CompositeDestination> _destinationGraph;
QuadMap _quadMap;
osg::ref_ptr<osgTerrain::CoordinateSystem> _coordinateSystem;
osg::Matrixd _geoTransform;

View File

@ -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;

View File

@ -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]; }

View File

@ -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<field.getNumColumns();++col,u+=du)
{
vertTop.x() = dx*(float)col;
vertTop.z() = field.getHeight(col,0);
normTop.set(field.getNormal(col,0));
glTexCoord2f(u,0.0f);
glNormal3fv(normTop.ptr());
glVertex3fv(vertTop.ptr());
vertTop.z()-=field.getSkirtHeight();
glVertex3fv(vertTop.ptr());
}
glEnd();
// draw top skirt
glBegin(GL_QUAD_STRIP);
unsigned int row = field.getNumRows()-1;
u = 0.0f;
vertTop.y() = dy*(float)(row);
for(col=0;col<field.getNumColumns();++col,u+=du)
{
vertTop.x() = dx*(float)col;
vertTop.z() = field.getHeight(col,row);
normTop.set(field.getNormal(col,row));
glTexCoord2f(u,1.0f);
glNormal3fv(normTop.ptr());
glVertex3f(vertTop.x(),vertTop.y(),vertTop.z()-field.getSkirtHeight());
//vertTop.z()-=field.getSkirtHeight();
glVertex3fv(vertTop.ptr());
}
glEnd();
}
for(unsigned int row=0;row<field.getNumRows()-1;++row,vBase+=dv)
{
float vTop = vBase+dv;
float u = 0.0f;
glBegin(GL_QUAD_STRIP);
// draw skirt at begining if required.
if (field.getSkirtHeight()!=0.0f)
{
vertTop.set(0.0f,dy*(float)row+dy,field.getHeight(0,row+1)-field.getSkirtHeight());
normTop.set(field.getNormal(0,row+1));
vertBase.set(0.0f,dy*(float)row,field.getHeight(0,row)-field.getSkirtHeight());
normBase.set(field.getNormal(0,row));
glTexCoord2f(u,vTop);
glNormal3fv(normTop.ptr());
glVertex3fv(vertTop.ptr());
glTexCoord2f(u,vBase);
glNormal3fv(normBase.ptr());
glVertex3fv(vertBase.ptr());
}
for(unsigned int col=0;col<field.getNumColumns();++col,u+=du)
{
Vec3 vertTop(dx*(float)col,dy*(float)row+dy,field.getHeight(col,row+1));
Vec3 normTop(field.getNormal(col,row+1));
vertTop.set(dx*(float)col,dy*(float)row+dy,field.getHeight(col,row+1));
normTop.set(field.getNormal(col,row+1));
Vec3 vertBase(dx*(float)col,dy*(float)row,field.getHeight(col,row));
Vec3 normBase(field.getNormal(col,row));
vertBase.set(dx*(float)col,dy*(float)row,field.getHeight(col,row));
normBase.set(field.getNormal(col,row));
glTexCoord2f(u,vTop);
glNormal3fv(normTop.ptr());
@ -604,6 +686,22 @@ void DrawShapeVisitor::apply(const HeightField& field)
}
// draw skirt at end if required.
if (field.getSkirtHeight()!=0.0f)
{
vertBase.z()-=field.getSkirtHeight();
vertTop.z()-=field.getSkirtHeight();
glTexCoord2f(u,vTop);
glNormal3fv(normTop.ptr());
glVertex3fv(vertTop.ptr());
glTexCoord2f(u,vBase);
glNormal3fv(normBase.ptr());
glVertex3fv(vertBase.ptr());
}
glEnd();
}

View File

@ -358,6 +358,24 @@ bool HeightField_readLocalData(Object& obj, Input& fr)
iteratorAdvanced = true;
}
if (fr.matchSequence("SkirtHeight %f"))
{
float height;
fr[1].getFloat(height);
heightfield.setSkirtHeight(height);
fr+=2;
iteratorAdvanced = true;
}
if (fr.matchSequence("BorderWidth %i"))
{
unsigned int width;
fr[1].getUInt(width);
heightfield.setBorderWidth(width);
fr+=2;
iteratorAdvanced = true;
}
if (fr.matchSequence("Rotation %f %f %f %f"))
{
osg::Quat rotation;
@ -426,6 +444,8 @@ bool HeightField_writeLocalData(const Object& obj, Output& fw)
fw.indent()<<"Origin "<<heightfield.getOrigin().x()<<" "<<heightfield.getOrigin().y()<<" "<<heightfield.getOrigin().z()<<std::endl;
fw.indent()<<"XInterval "<<heightfield.getXInterval()<<std::endl;
fw.indent()<<"YInterval "<<heightfield.getYInterval()<<std::endl;
fw.indent()<<"SkirtHeight "<<heightfield.getSkirtHeight()<<std::endl;
fw.indent()<<"BorderWidth "<<heightfield.getBorderWidth()<<std::endl;
fw.indent()<<"Rotation "<<heightfield.getRotation()<<std::endl;
fw.precision(prec);