OpenSceneGraph/include/osgTerrain/DataSet

1289 lines
48 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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. See the
* OpenSceneGraph Public License for more details.
*/
#ifdef WIN32
/////////////////////////////////////////////////////////////////////////////
// Disable unavoidable warning messages:
//
// C4503 - decorated name length exceeded, name was truncated
//
#pragma warning(disable : 4503)
#endif // WIN32
#ifndef DATASET_H
#define DATASET_H 1
#include <osg/BoundingSphere>
#include <osg/Node>
#include <osg/Matrixd>
#include <osg/Image>
#include <osg/Shape>
#include <osg/CoordinateSystemNode>
#include <osg/State>
#include <osgDB/Archive>
#include <set>
#include <osgTerrain/Export>
// forward declare so we can avoid tieing osgTerrain to GDAL.
class GDALDataset;
class GDALRasterBand;
namespace osgTerrain
{
#define MAXIMUM_NUMBER_OF_LEVELS 30
class GeospatialExtents
{
public:
osg::Vec2d _min;
osg::Vec2d _max;
bool _isGeographic;
inline GeospatialExtents() :
_min(DBL_MAX,DBL_MAX),
_max(-DBL_MAX,-DBL_MAX),
_isGeographic(false) {}
inline GeospatialExtents(double xmin, double ymin, double xmax, double ymax, bool isGeographic) :
_min(xmin, ymin),
_max(xmax, ymax),
_isGeographic(isGeographic) {}
inline double& xMin() { return _min.x(); }
inline double xMin() const { return _min.x(); }
inline double& yMin() { return _min.y(); }
inline double yMin() const { return _min.y(); }
inline double& xMax() { return _max.x(); }
inline double xMax() const { return _max.x(); }
inline double& yMax() { return _max.y(); }
inline double yMax() const { return _max.y(); }
inline void init()
{
_min.set(DBL_MAX,DBL_MAX);
_max.set(-DBL_MAX,-DBL_MAX);
}
inline bool valid() const
{
return _max.x()>=_min.x() && _max.y()>=_min.y();
}
inline double radius() const
{
return sqrt((radius2()));
}
inline double radius2() const
{
return 0.25f*((_max-_min).length2());
}
GeospatialExtents intersection(const GeospatialExtents& e, double xoffset) const
{
return GeospatialExtents(osg::maximum(xMin(),e.xMin()+xoffset),osg::maximum(yMin(),e.yMin()),
osg::minimum(xMax(),e.xMax()+xoffset),osg::minimum(yMax(),e.yMax()),_isGeographic);
}
/** Return true if this bounding box intersects the specified bounding box. */
bool intersects(const GeospatialExtents& bb) const
{
if (_isGeographic)
{
// first check vertical axis overlap
if (osg::maximum(yMin(),bb.yMin()) > osg::minimum(yMax(),bb.yMax())) return false;
// next check if overlaps directly without any 360 degree horizontal shifts.
if (osg::maximum(xMin(),bb.xMin()) <= osg::minimum(xMax(),bb.xMax())) return true;
// next check if a 360 rotation will produce an overlap
float rotationAngle = (xMin() > bb.xMin()) ? 360.0 : -360;
return (osg::maximum(xMin(),bb.xMin()+rotationAngle) <= osg::minimum(xMax(),bb.xMax()+rotationAngle));
}
else
{
return (osg::maximum(xMin(),bb.xMin()) <= osg::minimum(xMax(),bb.xMax()) &&
osg::maximum(yMin(),bb.yMin()) <= osg::minimum(yMax(),bb.yMax()));
}
}
void expandBy(const osg::BoundingSphere& sh)
{
if (!sh.valid()) return;
if(sh._center.x()-sh._radius<_min.x()) _min.x() = sh._center.x()-sh._radius;
if(sh._center.x()+sh._radius>_max.x()) _max.x() = sh._center.x()+sh._radius;
if(sh._center.y()-sh._radius<_min.y()) _min.y() = sh._center.y()-sh._radius;
if(sh._center.y()+sh._radius>_max.y()) _max.y() = sh._center.y()+sh._radius;
}
inline void expandBy(const osg::Vec3& v)
{
if(v.x()<_min.x()) _min.x() = v.x();
if(v.x()>_max.x()) _max.x() = v.x();
if(v.y()<_min.y()) _min.y() = v.y();
if(v.y()>_max.y()) _max.y() = v.y();
}
void expandBy(const GeospatialExtents& e)
{
if (!e.valid()) return;
if(e._min.x()<_min.x()) _min.x() = e._min.x();
if(e._max.x()>_max.x()) _max.x() = e._max.x();
if(e._min.y()<_min.y()) _min.y() = e._min.y();
if(e._max.y()>_max.y()) _max.y() = e._max.y();
}
};
class OSGTERRAIN_EXPORT DataSet : public osg::Referenced
{
public:
static std::string coordinateSystemStringToWTK(const std::string& coordinateSystem);
class Source;
struct OSGTERRAIN_EXPORT SpatialProperties
{
SpatialProperties():
_numValuesX(0),
_numValuesY(0),
_numValuesZ(0) {}
SpatialProperties(const SpatialProperties& sp):
_cs(sp._cs),
_geoTransform(sp._geoTransform),
_extents(sp._extents),
_numValuesX(sp._numValuesX),
_numValuesY(sp._numValuesY),
_numValuesZ(sp._numValuesZ) {}
SpatialProperties(osg::CoordinateSystemNode* cs, const GeospatialExtents& extents):
_cs(cs),
_extents(extents),
_numValuesX(0),
_numValuesY(0),
_numValuesZ(0) {}
inline SpatialProperties& assignSpatialProperties(const SpatialProperties& sp)
{
if (&sp==this) return *this;
_cs = sp._cs;
_geoTransform = sp._geoTransform;
_extents = sp._extents;
_numValuesX = sp._numValuesX;
_numValuesY = sp._numValuesY;
_numValuesZ = sp._numValuesZ;
return *this;
}
void computeExtents();
osg::ref_ptr<osg::CoordinateSystemNode> _cs;
osg::Matrixd _geoTransform;
GeospatialExtents _extents;
unsigned int _numValuesX;
unsigned int _numValuesY;
unsigned int _numValuesZ;
};
struct DestinationData : public osg::Referenced, SpatialProperties
{
DestinationData(DataSet* dataSet):
_dataSet(dataSet),
_minDistance(0.0),
_maxDistance(FLT_MAX) {}
typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
typedef std::vector< osg::ref_ptr<osg::Node> > ModelList;
DataSet* _dataSet;
float _minDistance;
float _maxDistance;
osg::ref_ptr<osg::Image> _image;
osg::ref_ptr<osg::HeightField> _heightField;
ModelList _models;
};
struct OSGTERRAIN_EXPORT SourceData : public osg::Referenced, public SpatialProperties
{
SourceData(Source* source=0):
_source(source),
_hasGCPs(false),
_gdalDataset(0) {}
virtual ~SourceData();
static SourceData* readData(Source* source);
GeospatialExtents getExtents(const osg::CoordinateSystemNode* cs) const;
const SpatialProperties& computeSpatialProperties(const osg::CoordinateSystemNode* cs) const;
bool intersects(const SpatialProperties& sp) const;
void read(DestinationData& destination);
virtual void readImage(DestinationData& destination);
virtual void readHeightField(DestinationData& destination);
virtual void readModels(DestinationData& destination);
float getInterpolatedValue(GDALRasterBand *band, double x, double y);
Source* _source;
bool _hasGCPs;
osg::ref_ptr<osg::Node> _model;
GDALDataset* _gdalDataset;
typedef std::map<const osg::CoordinateSystemNode*,SpatialProperties> SpatialPropertiesMap;
mutable SpatialPropertiesMap _spatialPropertiesMap;
};
class OSGTERRAIN_EXPORT Source : public osg::Referenced, public SpatialProperties
{
public:
enum Type
{
IMAGE,
HEIGHT_FIELD,
MODEL
};
enum ParameterPolicy
{
PREFER_CONFIG_SETTINGS,
PREFER_CONFIG_SETTINGS_BUT_SCALE_BY_FILE_RESOLUTION,
PREFER_FILE_SETTINGS
};
Source():
_type(IMAGE),
_sortValue(0.0),
_temporaryFile(false),
_coordinateSystemPolicy(PREFER_FILE_SETTINGS),
_geoTransformPolicy(PREFER_FILE_SETTINGS),
_minLevel(0),
_maxLevel(MAXIMUM_NUMBER_OF_LEVELS),
_layer(0),
_gdalDataset(0)
{}
Source(Type type, const std::string& filename):
_type(type),
_sortValue(0.0),
_filename(filename),
_temporaryFile(false),
_coordinateSystemPolicy(PREFER_FILE_SETTINGS),
_geoTransformPolicy(PREFER_FILE_SETTINGS),
_minLevel(0),
_maxLevel(MAXIMUM_NUMBER_OF_LEVELS),
_layer(0),
_gdalDataset(0)
{}
void setSortValue(double s) { _sortValue = s; }
double getSortValue() const { return _sortValue; }
void setSortValueFromSourceDataResolution();
void setType(Type type) { _type = type; }
Type getType() const { return _type; }
void setFileName(const std::string& filename) { _filename = filename; }
const std::string& getFileName() const { return _filename; }
void setTemporaryFile(bool temporaryFile) { _temporaryFile = temporaryFile; }
bool getTemporaryFile() const { return _temporaryFile; }
void setGdalDataset(void* gdalDataset);
void* getGdalDataset();
const void* getGdalDataset() const;
void setCoordinateSystemPolicy(ParameterPolicy policy) { _coordinateSystemPolicy = policy; }
ParameterPolicy getCoordinateSystemPolicy() const { return _coordinateSystemPolicy; }
void setCoordinateSystem(const std::string& wellKnownText) { _cs = new osg::CoordinateSystemNode("WKT",wellKnownText); }
void setCoordinateSystem(osg::CoordinateSystemNode* cs) { _cs = cs; }
osg::CoordinateSystemNode* getCoordinateSystem() { return _cs.get(); }
void setGeoTransformPolicy(ParameterPolicy policy) { _geoTransformPolicy = policy; }
ParameterPolicy getGeoTransformPolicy() const { return _geoTransformPolicy; }
void setGeoTransform(osg::Matrixd& transform) { _geoTransform = transform; }
osg::Matrixd& getGeoTransform() { return _geoTransform; }
void setGeoTransformFromRange(double xMin, double xMax, double yMin, double yMax)
{
_geoTransform.makeIdentity();
_geoTransform(0,0) = xMax-xMin;
_geoTransform(3,0) = xMin;
_geoTransform(1,1) = yMax-yMin;
_geoTransform(3,1) = yMin;
}
void assignCoordinateSystemAndGeoTransformAccordingToParameterPolicy();
void setMinLevel(unsigned int minLevel) { _minLevel = minLevel; }
void setMaxLevel(unsigned int maxLevel) { _maxLevel = maxLevel; }
void setMinMaxLevel(unsigned int minLevel, unsigned int maxLevel) { _minLevel = minLevel; _maxLevel = maxLevel; }
unsigned int getMinLevel() const { return _minLevel; }
unsigned int getMaxLevel() const { return _maxLevel; }
void setLayer(unsigned int layer) { _layer = layer; }
unsigned int getLayer() const { return _layer; }
void setSourceData(SourceData* data) { _sourceData = data; if (_sourceData.valid()) _sourceData->_source = this; }
SourceData* getSourceData() { return _sourceData.get(); }
bool intersects(const SpatialProperties& sp) const
{
return _sourceData.valid()?_sourceData->intersects(sp):false;
}
void loadSourceData();
bool needReproject(const osg::CoordinateSystemNode* cs) const;
bool needReproject(const osg::CoordinateSystemNode* cs, double minResolution, double maxResolution) const;
Source* doReproject(const std::string& filename, osg::CoordinateSystemNode* cs, double targetResolution=0.0) const;
void buildOverviews();
struct ResolutionPair
{
ResolutionPair():
_resX(0.0),_resY(0.0) {}
ResolutionPair(double x,double y):
_resX(x),_resY(y) {}
bool operator < (const ResolutionPair& rhs) const
{
double minLHS = osg::minimum(_resX,_resY);
double minRHS = osg::minimum(rhs._resX,rhs._resY);
return minLHS<minRHS;
}
double _resX;
double _resY;
};
typedef std::vector<ResolutionPair> ResolutionList;
void addRequiredResolution(double resX, double resY) { _requiredResolutions.push_back(ResolutionPair(resX,resY)); }
void setRequiredResolutions(ResolutionList& resolutions) { _requiredResolutions = resolutions; }
ResolutionList& getRequiredResolutions() { return _requiredResolutions; }
const ResolutionList& getRequiredResolutions() const { return _requiredResolutions; }
void consolodateRequiredResolutions();
protected:
Type _type;
double _sortValue;
std::string _filename;
bool _temporaryFile;
ParameterPolicy _coordinateSystemPolicy;
ParameterPolicy _geoTransformPolicy;
unsigned int _minLevel;
unsigned int _maxLevel;
unsigned int _layer;
osg::ref_ptr<SourceData> _sourceData;
ResolutionList _requiredResolutions;
GDALDataset* _gdalDataset;
};
enum CompositeType
{
GROUP,
LOD,
PAGED_LOD
};
class OSGTERRAIN_EXPORT CompositeSource : public osg::Referenced, public SpatialProperties
{
public:
CompositeSource(CompositeType type=GROUP):_type(type) {};
typedef std::vector< osg::ref_ptr<Source> > SourceList;
typedef std::vector< osg::ref_ptr< CompositeSource> > ChildList;
void setType(CompositeType type) { _type = type; }
CompositeType getType() const { return _type; }
void setSortValueFromSourceDataResolution();
void sort();
class iterator
{
public:
enum IteratorMode
{
ACTIVE,
ALL
};
iterator(CompositeSource* composite=0,IteratorMode mode=ALL):
_iteratorMode(mode)
{
if (composite)
{
_positionStack.push_back(IteratorPosition(composite));
}
}
iterator(const iterator& rhs):
_positionStack(rhs._positionStack) {}
iterator& operator = (const iterator& rhs)
{
if (&rhs==this) return *this;
_positionStack = rhs._positionStack;
return *this;
}
bool operator == (const iterator& rhs) const
{
return _positionStack == rhs._positionStack;
}
bool operator != (const iterator& rhs) const
{
return _positionStack != rhs._positionStack;
}
bool valid() const
{
return !_positionStack.empty() && _positionStack.back().valid();
}
CompositeSource& operator *()
{
return *(valid()?_positionStack.back().current():0);
}
CompositeSource* operator ->()
{
return valid()?_positionStack.back().current():0;
}
const CompositeSource& operator *() const
{
return *(valid()?_positionStack.back().current():0);
}
const CompositeSource* operator ->() const
{
return valid()?_positionStack.back().current():0;
}
iterator& operator++()
{
advance();
return *this;
}
iterator operator++(int)
{
iterator tmp=*this;
advance();
return tmp;
}
bool advance()
{
if (_positionStack.empty()) return false;
// simple advance to the next source
if (_positionStack.back().advance())
{
if (_positionStack.back().current())
{
_positionStack.push_back(IteratorPosition(_positionStack.back().current()));
return advance();
}
}
_positionStack.pop_back();
return advance();
}
protected:
struct IteratorPosition
{
IteratorPosition(CompositeSource* composite):
_composite(composite),
_index(-1) {}
IteratorPosition(const IteratorPosition& rhs):
_composite(rhs._composite),
_index(rhs._index) {}
IteratorPosition& operator = (const IteratorPosition& rhs)
{
_composite = rhs._composite;
_index = rhs._index;
return *this;
}
bool operator == (const IteratorPosition& rhs) const
{
return _composite == rhs._composite && _index == rhs._index;
}
bool operator != (const IteratorPosition& rhs) const
{
return _composite != rhs._composite || _index != rhs._index;
}
CompositeSource* current()
{
if (_index==-1) return _composite;
else return (_index>=0 && _index < (int)_composite->_children.size())?_composite->_children[_index].get():0;
}
const CompositeSource* current() const
{
if (_index==-1) return _composite;
else return (_index>=0 && _index < (int)_composite->_children.size())?_composite->_children[_index].get():0;
}
bool valid() const
{
return _composite &&
_index < (int)_composite->_children.size();
}
inline bool advance()
{
return advanceToNextChild(*_composite,_index);
}
inline bool isActive(const CompositeSource& /*composite*/,int /*index*/)
{
return true;
}
inline bool advanceToNextChild(CompositeSource& composite, int& index)
{
++index;
while (index<(int)composite._children.size())
{
if (isActive(composite,index)) return true;
++index;
}
return false;
}
CompositeSource* _composite;
int _index;
};
typedef std::vector<IteratorPosition> PositionStack;
IteratorMode _iteratorMode;
PositionStack _positionStack;
};
template<class T>
class base_source_iterator
{
public:
base_source_iterator(CompositeSource* composite=0, T advancer=T()):
_advancer(advancer),
_compositeIterator(composite),
_sourceIndex(-1)
{
advance();
}
base_source_iterator(const base_source_iterator& rhs):
_advancer(rhs._advancer),
_compositeIterator(rhs._compositeIterator),
_sourceIndex(rhs._sourceIndex) {}
base_source_iterator& operator = (const base_source_iterator& rhs)
{
if (&rhs==this) return *this;
_advancer = rhs._advancer;
_compositeIterator = rhs._compositeIterator;
_sourceIndex = rhs._sourceIndex;
}
bool operator == (const base_source_iterator& rhs) const
{
return _compositeIterator == rhs._compositeIterator &&
_sourceIndex == rhs._sourceIndex;
}
bool operator != (const base_source_iterator& rhs) const
{
return _compositeIterator != rhs._compositeIterator ||
_sourceIndex != rhs._sourceIndex;
}
bool valid() const
{
return _compositeIterator.valid() && _sourceIndex < (int)_compositeIterator->_sourceList.size();
}
osg::ref_ptr<Source>& operator *()
{
return valid()?_compositeIterator->_sourceList[_sourceIndex]:_nullSource;
}
osg::ref_ptr<Source>* operator ->()
{
return &(valid()?_compositeIterator->_sourceList[_sourceIndex]:_nullSource);
}
base_source_iterator& operator++()
{
advance();
return *this;
}
base_source_iterator operator++(int)
{
base_source_iterator tmp=*this;
advance();
return tmp;
}
bool advance()
{
if (!_compositeIterator.valid()) return false;
if (_advancer.advanceToNextSource(*_compositeIterator,_sourceIndex)) return true;
// at end of current CompositeSource, so need to advance to new one.
_sourceIndex = -1;
++_compositeIterator;
return advance();
}
protected:
T _advancer;
iterator _compositeIterator;
int _sourceIndex;
osg::ref_ptr<Source> _nullSource;
};
struct DefaultSourceAdvancer
{
DefaultSourceAdvancer() {}
bool isActive(const CompositeSource& /*composite*/,int /*index*/)
{
return true;
}
inline bool advanceToNextSource(const CompositeSource& composite, int& index)
{
return ++index<(int)composite._sourceList.size();
}
};
struct LODSourceAdvancer
{
LODSourceAdvancer(float targetResolution=0.0f):
_targetResolution(targetResolution) {}
inline bool advanceToNextSource(const CompositeSource& composite, int& index)
{
if (composite.getType()==GROUP)
{
return (++index<(int)composite._sourceList.size());
}
else
{
if (composite._sourceList.empty()) return false;
if (index!=-1) return false; // we've already traversed this composite, only ever one valid LOD.
// find source with resolution closest to target
int foundIndex = 0;
float closestResolution = fabsf(composite._sourceList[0]->getSortValue()-_targetResolution);
for(int i=1;i<(int)composite._sourceList.size();++i)
{
float delta = fabsf(composite._sourceList[i]->getSortValue()-_targetResolution);
if (delta<closestResolution)
{
foundIndex = i;
closestResolution = delta;
}
}
if (foundIndex==index) return false;
index = foundIndex;
return true;
}
}
float _targetResolution;
};
typedef base_source_iterator<DefaultSourceAdvancer> source_iterator;
typedef base_source_iterator<LODSourceAdvancer> source_lod_iterator;
CompositeType _type;
SourceList _sourceList;
ChildList _children;
};
class OSGTERRAIN_EXPORT DestinationTile : public osg::Referenced, public SpatialProperties
{
public:
enum Position
{
LEFT = 0,
LEFT_BELOW = 1,
BELOW = 2,
BELOW_RIGHT = 3,
RIGHT = 4,
RIGHT_ABOVE = 5,
ABOVE = 6,
ABOVE_LEFT = 7,
NUMBER_OF_POSITIONS = 8
};
DestinationTile();
void computeNeighboursFromQuadMap();
void setNeighbours(DestinationTile* left, DestinationTile* left_below,
DestinationTile* below, DestinationTile* below_right,
DestinationTile* right, DestinationTile* right_above,
DestinationTile* above, DestinationTile* above_left);
void checkNeighbouringTiles();
void setMaximumImagerySize(unsigned int maxNumColumns,unsigned int maxNumRows)
{
_imagery_maxNumColumns = maxNumColumns;
_imagery_maxNumRows = maxNumRows;
}
void setMaximumTerrainSize(unsigned int maxNumColumns,unsigned int maxNumRows)
{
_terrain_maxNumColumns = maxNumColumns;
_terrain_maxNumRows = maxNumRows;
}
void computeMaximumSourceResolution(CompositeSource* sourceGraph);
bool computeImageResolution(unsigned int layer, unsigned int& numColumns, unsigned int& numRows, double& resX, double& resY);
bool computeTerrainResolution(unsigned int& numColumns, unsigned int& numRows, double& resX, double& resY);
void allocate();
void addRequiredResolutions(CompositeSource* sourceGraph);
void readFrom(CompositeSource* sourceGraph);
void allocateEdgeNormals();
void equalizeCorner(Position position);
void equalizeEdge(Position position);
void equalizeBoundaries();
void setTileComplete(bool complete);
bool getTileComplete() const { return _complete; }
void optimizeResolution();
osg::Node* createScene();
osg::StateSet* createStateSet();
osg::Node* createHeightField();
osg::Node* createPolygonal();
void unrefData();
DataSet* _dataSet;
std::string _name;
unsigned int _level;
unsigned int _tileX;
unsigned int _tileY;
GLenum _pixelFormat;
struct ImageData
{
ImageData():
_imagery_maxSourceResolutionX(0.0f),
_imagery_maxSourceResolutionY(0.0f) {}
float _imagery_maxSourceResolutionX;
float _imagery_maxSourceResolutionY;
osg::ref_ptr<DestinationData> _imagery;
};
std::vector<ImageData> _imagery;
inline ImageData& getImageData(unsigned int layer)
{
if (layer>=_imagery.size()) _imagery.resize(layer+1);
return _imagery[layer];
}
osg::ref_ptr<DestinationData> _terrain;
osg::ref_ptr<DestinationData> _models;
DestinationTile* _neighbour[NUMBER_OF_POSITIONS];
bool _equalized[NUMBER_OF_POSITIONS];
unsigned int _maxSourceLevel;
unsigned int _imagery_maxNumColumns;
unsigned int _imagery_maxNumRows;
unsigned int _terrain_maxNumColumns;
unsigned int _terrain_maxNumRows;
float _terrain_maxSourceResolutionX;
float _terrain_maxSourceResolutionY;
bool _complete;
typedef std::vector<osg::Vec2> HeightDeltaList;
HeightDeltaList _heightDeltas[NUMBER_OF_POSITIONS];
};
class OSGTERRAIN_EXPORT CompositeDestination : public osg::Referenced, public SpatialProperties
{
public:
CompositeDestination():
_dataSet(0),
_parent(0),
_level(0),
_tileX(0),
_tileY(0),
_type(GROUP),
_maxVisibleDistance(FLT_MAX),
_subTileGenerated(false) {}
CompositeDestination(osg::CoordinateSystemNode* cs, const GeospatialExtents& extents):
SpatialProperties(cs,extents),
_dataSet(0),
_parent(0),
_level(0),
_tileX(0),
_tileY(0),
_type(GROUP),
_maxVisibleDistance(FLT_MAX),
_subTileGenerated(false) {}
void computeNeighboursFromQuadMap();
void addRequiredResolutions(CompositeSource* sourceGraph);
void readFrom(CompositeSource* sourceGraph);
void equalizeBoundaries();
osg::Node* createScene();
bool areSubTilesComplete();
std::string getSubTileName();
osg::Node* createPagedLODScene();
osg::Node* createSubTileScene();
void unrefSubTileData();
void unrefLocalData();
void setSubTilesGenerated(bool generated) { _subTileGenerated=generated; }
bool getSubTilesGenerated() const { return _subTileGenerated; }
typedef std::vector< osg::ref_ptr<DestinationTile> > TileList;
typedef std::vector< osg::ref_ptr<CompositeDestination> > ChildList;
DataSet* _dataSet;
CompositeDestination* _parent;
std::string _name;
unsigned int _level;
unsigned int _tileX;
unsigned int _tileY;
CompositeType _type;
TileList _tiles;
ChildList _children;
float _maxVisibleDistance;
bool _subTileGenerated;
};
typedef std::map<unsigned int,CompositeDestination*> Row;
typedef std::map<unsigned int,Row> Level;
typedef std::map<unsigned int,Level> QuadMap;
void insertTileToQuadMap(CompositeDestination* tile)
{
_quadMap[tile->_level][tile->_tileY][tile->_tileX] = tile;
}
DestinationTile* getTile(unsigned int level,unsigned int X, unsigned int Y)
{
CompositeDestination* cd = getComposite(level,X,Y);
if (!cd) return 0;
if (cd->_tiles.empty()) return 0;
return (cd->_tiles).front().get();
}
CompositeDestination* getComposite(unsigned int level,unsigned int X, unsigned int Y)
{
QuadMap::iterator levelItr = _quadMap.find(level);
if (levelItr==_quadMap.end()) return 0;
Level::iterator rowItr = levelItr->second.find(Y);
if (rowItr==levelItr->second.end()) return 0;
Row::iterator columnItr = rowItr->second.find(X);
if (columnItr==rowItr->second.end()) return 0;
else return columnItr->second;
}
Row& getRow(unsigned int level,unsigned int Y)
{
return _quadMap[level][Y];
}
public:
DataSet();
void addSource(Source* source);
void addSource(CompositeSource* composite);
void loadSources();
void setMaximumTileImageSize(unsigned int size) { _maximumTileImageSize = size; }
unsigned int getMaximumTileImageSize() const { return _maximumTileImageSize; }
void setMaximumTileTerrainSize(unsigned int size) { _maximumTileTerrainSize = size; }
unsigned int getMaximumTileTerrainSize() const { return _maximumTileTerrainSize; }
void setMaximumVisibleDistanceOfTopLevel(float d) { _maximumVisiableDistanceOfTopLevel = d; }
float getMaximumVisibleDistanceOfTopLevel() const { return _maximumVisiableDistanceOfTopLevel; }
void setRadiusToMaxVisibleDistanceRatio(float ratio) { _radiusToMaxVisibleDistanceRatio = ratio; }
float getRadiusToMaxVisibleDistanceRatio() const { return _radiusToMaxVisibleDistanceRatio; }
void setVerticalScale(float verticalScale) { _verticalScale = verticalScale; }
float getVerticalScale() const { return _verticalScale; }
void setSkirtRatio(float skirtRatio) { _skirtRatio = skirtRatio; }
float getSkirtRatio() const { return _skirtRatio; }
void setDefaultColor(const osg::Vec4& defaultColor) { _defaultColor = defaultColor; }
const osg::Vec4& getDefaultColor() const { return _defaultColor; }
void setDestinationCoordinateSystem(const std::string& wellKnownText) { setDestinationCoordinateSystem(new osg::CoordinateSystemNode("WKT",wellKnownText)); }
void setDestinationCoordinateSystem(osg::CoordinateSystemNode* cs) { _destinationCoordinateSystem = cs; }
osg::CoordinateSystemNode* getDestinationCoordinateSystem() { return _destinationCoordinateSystem .get(); }
void setIntermediateCoordinateSystem(const std::string& wellKnownText) { setIntermediateCoordinateSystem(new osg::CoordinateSystemNode("WKT",wellKnownText)); }
void setIntermediateCoordinateSystem(osg::CoordinateSystemNode* cs) { _intermediateCoordinateSystem = cs; }
osg::CoordinateSystemNode* getIntermediateCoordinateSystem() { return _intermediateCoordinateSystem.get(); }
void setConvertFromGeographicToGeocentric(bool flag) { _convertFromGeographicToGeocentric = flag; }
bool getConvertFromGeographicToGeocentric() const { return _convertFromGeographicToGeocentric; }
void setEllipsoidModel(osg::EllipsoidModel* et) { _ellipsoidModel = et; }
osg::EllipsoidModel* getEllipsoidModel() { return _ellipsoidModel.get(); }
const osg::EllipsoidModel* getEllipsoidModel() const { return _ellipsoidModel.get(); }
bool mapLatLongsToXYZ() const { return getConvertFromGeographicToGeocentric() && getEllipsoidModel(); }
void setDestinationExtents(const GeospatialExtents& extents) { _extents = extents; }
void setDestinationGeoTransform(const osg::Matrixd& geoTransform) { _geoTransform = geoTransform; }
/** Set the Archive name if one is to be used.*/
void setArchiveName(const std::string& filename) { _archiveName = filename; }
/** Get the Archive name.*/
const std::string& getArchiveName() const { return _archiveName; }
/** Set the Archive.*/
void setArchive(osgDB::Archive* archive) { _archive = archive; }
/** Get the Archive if one is to being used.*/
osgDB::Archive* getArchive() { return _archive.get(); }
/** Set the Directory, DestinationTileBaseName and DestinationTileExtension from the passed in filename.*/
void setDestinationName(const std::string& filename);
void setDirectory(const std::string& directory);
const std::string& getDirectory() const { return _directory; }
void setDestinationTileBaseName(const std::string& basename) { _tileBasename = basename; }
const std::string& getDestinationTileBaseName() const { return _tileBasename; }
void setDestinationTileExtension(const std::string& extension) { _tileExtension = extension; }
const std::string& getDestinationTileExtension() const { return _tileExtension; }
void setDestinationImageExtension(const std::string& extension) { _imageExtension = extension; }
const std::string& getDestinationImageExtension() const { return _imageExtension; }
enum DatabaseType
{
LOD_DATABASE,
PagedLOD_DATABASE,
};
void setDatabaseType(DatabaseType type) { _databaseType = type; }
DatabaseType getDatabaseType() const { return _databaseType; }
enum GeometryType
{
HEIGHT_FIELD,
POLYGONAL,
};
void setGeometryType(GeometryType type) { _geometryType = type; }
GeometryType getGeometryType() const { return _geometryType; }
enum TextureType
{
RGB_24,
RGBA,
RGB_16,
RGBA_16,
COMPRESSED_TEXTURE,
COMPRESSED_RGBA_TEXTURE
};
void setTextureType(TextureType type) { _textureType = type; }
TextureType getTextureType() const { return _textureType; }
void setMaxAnisotropy(float d) { _maxAnisotropy = d; }
float getMaxAnisotropy() const { return _maxAnisotropy; }
enum MipMappingMode
{
NO_MIP_MAPPING, /// disable mip mapping - use LINEAR, LINEAR filters.
MIP_MAPPING_HARDWARE, /// use mip mapping, dynamically compute them in hardware if supported
MIP_MAPPING_IMAGERY /// use mip mapping, and store imagery along with associated mip maps.
};
void setMipMappingMode(MipMappingMode mipMappingMode) { _mipMappingMode = mipMappingMode; }
MipMappingMode getMipMappingMode() const { return _mipMappingMode; }
void setUseLocalTileTransform(bool flag) { _useLocalTileTransform = flag; }
bool getUseLocalTileTransform() const { return _useLocalTileTransform; }
void setSimplifyTerrain(bool flag) { _simplifyTerrain = flag; }
bool getSimplifyTerrain() const { return _simplifyTerrain; }
void setDecorateGeneratedSceneGraphWithCoordinateSystemNode(bool flag) { _decorateWithCoordinateSystemNode = flag; }
bool getDecorateGeneratedSceneGraphWithCoordinateSystemNode() const { return _decorateWithCoordinateSystemNode; }
void setDecorateGeneratedSceneGraphWithMultiTextureControl(bool flag) { _decorateWithMultiTextureControl = flag; }
bool getDecorateGeneratedSceneGraphWithMultiTextureControl() const { return _decorateWithMultiTextureControl; }
unsigned int getNumOfTextureLevels() const { return _numTextureLevels; }
void setCommentString(const std::string& comment) { _comment = comment; }
const std::string& getCommentString() const { return _comment; }
void setWriteNodeBeforeSimplification(bool flag) { _writeNodeBeforeSimplification = flag; }
bool getWriteNodeBeforeSimplification() const { return _writeNodeBeforeSimplification; }
static void setNotifyOffset(int level);
static int getNotifyOffset();
CompositeDestination* createDestinationGraph(CompositeDestination* parent,
osg::CoordinateSystemNode* cs,
const GeospatialExtents& extents,
unsigned int maxImageSize,
unsigned int maxTerrainSize,
unsigned int currentLevel,
unsigned int currentX,
unsigned int currentY,
unsigned int maxNumLevels);
void computeDestinationGraphFromSources(unsigned int numLevels);
void updateSourcesForDestinationGraphNeeds();
void populateDestinationGraphFromSources();
void createDestination(unsigned int numLevels);
void buildDestination() { _buildDestination(false); }
void writeDestination() { _buildDestination(true); }
osg::Node* getDestinationRootNode() { return _rootNode.get(); }
// helper functions for handling optional archive
void _writeNodeFile(const osg::Node& node,const std::string& filename);
void _writeImageFile(const osg::Image& image,const std::string& filename);
void setState(osg::State* state) { _state = state; }
osg::State* getState() { return _state.get(); }
protected:
virtual ~DataSet() {}
void _readRow(Row& row);
void _equalizeRow(Row& row);
void _writeRow(Row& row);
void _buildDestination(bool writeToDisk);
void init();
osg::Node* decorateWithCoordinateSystemNode(osg::Node* subgraph);
osg::Node* decorateWithMultiTextureControl(osg::Node* subgraph);
osg::ref_ptr<CompositeSource> _sourceGraph;
osg::ref_ptr<CompositeDestination> _destinationGraph;
QuadMap _quadMap;
unsigned int _maximumTileImageSize;
unsigned int _maximumTileTerrainSize;
float _maximumVisiableDistanceOfTopLevel;
float _radiusToMaxVisibleDistanceRatio;
float _verticalScale;
float _skirtRatio;
osg::ref_ptr<osg::CoordinateSystemNode> _destinationCoordinateSystem;
osg::ref_ptr<osg::CoordinateSystemNode> _intermediateCoordinateSystem;
bool _convertFromGeographicToGeocentric;
osg::ref_ptr<osg::EllipsoidModel> _ellipsoidModel;
osg::Matrixd _geoTransform;
GeospatialExtents _extents;
std::string _archiveName;
osg::ref_ptr<osgDB::Archive> _archive;
std::string _directory;
std::string _tileBasename;
std::string _tileExtension;
std::string _imageExtension;
osg::Vec4 _defaultColor;
DatabaseType _databaseType;
GeometryType _geometryType;
TextureType _textureType;
float _maxAnisotropy;
MipMappingMode _mipMappingMode;
unsigned int _numTextureLevels;
bool _useLocalTileTransform;
bool _decorateWithCoordinateSystemNode;
bool _decorateWithMultiTextureControl;
std::string _comment;
bool _writeNodeBeforeSimplification;
bool _simplifyTerrain;
osg::ref_ptr<osg::Node> _rootNode;
osg::ref_ptr<osg::State> _state;
};
}
#endif