6a103aa413
different texture layers.
1144 lines
43 KiB
C++
1144 lines
43 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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/Node>
|
|
#include <osg/Matrixd>
|
|
#include <osg/BoundingBox>
|
|
#include <osg/Image>
|
|
#include <osg/Shape>
|
|
#include <osg/CoordinateSystemNode>
|
|
|
|
#include <osgDB/Archive>
|
|
|
|
#include <set>
|
|
|
|
#include <osgTerrain/Export>
|
|
|
|
// forward declare so we can avoid tieing osgTerrain to GDAL.
|
|
class GDALDataset;
|
|
|
|
namespace osgTerrain
|
|
{
|
|
|
|
#define MAXIMUM_NUMBER_OF_LEVELS 30
|
|
|
|
class OSGTERRAIN_EXPORT DataSet : public osg::Referenced
|
|
{
|
|
public:
|
|
|
|
static std::string coordinateSystemStringToWTK(const std::string& coordinateSystem);
|
|
|
|
class Source;
|
|
|
|
struct 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 osg::BoundingBox& 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()
|
|
{
|
|
_extents.init();
|
|
_extents.expandBy( osg::Vec3(0.0,0.0,0.0)*_geoTransform);
|
|
_extents.expandBy( osg::Vec3(_numValuesX,_numValuesY,0.0)*_geoTransform);
|
|
}
|
|
|
|
osg::ref_ptr<osg::CoordinateSystemNode> _cs;
|
|
osg::Matrixd _geoTransform;
|
|
osg::BoundingBox _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 SourceData : public osg::Referenced, public SpatialProperties
|
|
{
|
|
|
|
SourceData(Source* source=0):
|
|
_source(source),
|
|
_hasGCPs(false),
|
|
_gdalDataSet(0) {}
|
|
|
|
virtual ~SourceData();
|
|
|
|
static SourceData* readData(Source* source);
|
|
|
|
osg::BoundingBox getExtents(const osg::CoordinateSystemNode* cs) const;
|
|
|
|
const SpatialProperties& computeSpatialProperties(const osg::CoordinateSystemNode* cs) const;
|
|
|
|
bool intersects(const SpatialProperties& sp) const;
|
|
|
|
void read(DestinationData& destination);
|
|
|
|
void readImage(DestinationData& destination);
|
|
void readHeightField(DestinationData& destination);
|
|
void readModels(DestinationData& destination);
|
|
|
|
Source* _source;
|
|
|
|
bool _hasGCPs;
|
|
|
|
osg::ref_ptr<osg::Node> _model;
|
|
GDALDataset* _gdalDataSet;
|
|
|
|
typedef std::map<const osg::CoordinateSystemNode*,SpatialProperties> SpatialPropertiesMap;
|
|
mutable SpatialPropertiesMap _spatialPropertiesMap;
|
|
|
|
|
|
};
|
|
|
|
|
|
class 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)
|
|
{}
|
|
|
|
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)
|
|
{}
|
|
|
|
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 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;
|
|
|
|
};
|
|
|
|
enum CompositeType
|
|
{
|
|
GROUP,
|
|
LOD,
|
|
PAGED_LOD
|
|
};
|
|
|
|
class 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 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 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;
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
class 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 osg::BoundingBox& 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 osg::BoundingBox& 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 DestinationTileBaseName and DestinationTileExtension from the passed in filename.*/
|
|
void setDestinationName(const std::string& filename);
|
|
|
|
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; }
|
|
|
|
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_BIT,
|
|
RGB_16_BIT,
|
|
COMPRESSED_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 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 setNotifyOffset();
|
|
|
|
|
|
CompositeDestination* createDestinationGraph(CompositeDestination* parent,
|
|
osg::CoordinateSystemNode* cs,
|
|
const osg::BoundingBox& 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);
|
|
|
|
|
|
|
|
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;
|
|
osg::BoundingBox _extents;
|
|
std::string _archiveName;
|
|
osg::ref_ptr<osgDB::Archive> _archive;
|
|
std::string _tileBasename;
|
|
std::string _tileExtension;
|
|
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;
|
|
|
|
osg::ref_ptr<osg::Node> _rootNode;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|