Improved the handling of building/writing generated databases, and

the fixed transition distances on the lower levels of geocentric databases.
This commit is contained in:
Robert Osfield 2004-09-13 13:53:45 +00:00
parent 8536e5dbdf
commit b664c20c74
4 changed files with 148 additions and 248 deletions

View File

@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\
osgsimulation.cpp\
LIBS += -losgProducer -lProducer -losgParticle -losgSim -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
LIBS += -losgTerrain -losgProducer -lProducer -losgParticle -losgSim -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
INSTFILES = \
$(CXXFILES)\

View File

@ -6,251 +6,81 @@
#include <osg/Texture2D>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osg/CoordinateSystemNode>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
#include <osgText/Text>
#include <osgSim/SphereSegment>
#include <osgParticle/ExplosionEffect>
#include <osgParticle/SmokeEffect>
#include <osgParticle/FireEffect>
#include <osgParticle/ParticleSystemUpdater>
#include <osgTerrain/DataSet>
#include <osgGA/NodeTrackerManipulator>
// for the grid data..
#include "../osghangglide/terrain_coords.h"
osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
{
// set up the animation path
osg::AnimationPath* animationPath = new osg::AnimationPath;
animationPath->setLoopMode(osg::AnimationPath::LOOP);
int numSamples = 40;
float yaw = 0.0f;
float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
float roll = osg::inDegrees(30.0f);
double time=0.0f;
double time_delta = looptime/(double)numSamples;
for(int i=0;i<numSamples;++i)
{
osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
osg::Quat rotation(osg::Quat(roll,osg::Vec3(0.0,1.0,0.0))*osg::Quat(-(yaw+osg::inDegrees(90.0f)),osg::Vec3(0.0,0.0,1.0)));
animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
yaw += yaw_delta;
time += time_delta;
}
return animationPath;
}
osg::Node* createMovingModel(const osg::Vec3& center, float radius)
{
float animationLength = 10.0f;
osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
osg::Group* model = new osg::Group;
osg::Node* glider = osgDB::readNodeFile("glider.osg");
if (glider)
{
glider->setName("glider");
const osg::BoundingSphere& bs = glider->getBound();
float size = radius/bs.radius()*0.3f;
osg::MatrixTransform* positioned = new osg::MatrixTransform;
positioned->setDataVariance(osg::Object::STATIC);
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
osg::Matrix::scale(size,size,size)*
osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f));
positioned->addChild(glider);
osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform;
xform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0));
xform->addChild(positioned);
model->addChild(xform);
}
osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
if (cessna)
{
cessna->setName("cessna");
const osg::BoundingSphere& bs = cessna->getBound();
osgText::Text* text = new osgText::Text;
float size = radius/bs.radius()*0.3f;
text->setPosition(bs.center());
text->setText("Cessna");
text->setAlignment(osgText::Text::CENTER_CENTER);
text->setAxisAlignment(osgText::Text::SCREEN);
text->setCharacterSize(40.0f);
text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(text);
osg::LOD* lod = new osg::LOD;
lod->setRangeMode(osg::LOD::PIXEL_SIZE_ON_SCREEN);
lod->addChild(geode,0.0f,100.0f);
lod->addChild(cessna,100.0f,10000.0f);
osg::MatrixTransform* positioned = new osg::MatrixTransform;
positioned->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
positioned->setDataVariance(osg::Object::STATIC);
positioned->setMatrix(osg::Matrix::translate(-bs.center())*
osg::Matrix::scale(size,size,size)*
osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f));
//positioned->addChild(cessna);
positioned->addChild(lod);
osg::MatrixTransform* xform = new osg::MatrixTransform;
xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
xform->addChild(positioned);
model->addChild(xform);
}
return model;
}
osg::Vec3 computeTerrainIntersection(osg::Node* subgraph,float x,float y)
{
osgUtil::IntersectVisitor iv;
osg::ref_ptr<osg::LineSegment> segDown = new osg::LineSegment;
const osg::BoundingSphere& bs = subgraph->getBound();
float zMax = bs.center().z()+bs.radius();
float zMin = bs.center().z()-bs.radius();
segDown->set(osg::Vec3(x,y,zMin),osg::Vec3(x,y,zMax));
iv.addLineSegment(segDown.get());
subgraph->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segDown.get());
if (!hitList.empty())
class GraphicsContext {
public:
GraphicsContext()
{
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
return ip;
}
}
return osg::Vec3(x,y,0.0f);
}
//////////////////////////////////////////////////////////////////////////////
// MAIN SCENE GRAPH BUILDING FUNCTION
//////////////////////////////////////////////////////////////////////////////
void build_world(osg::Group *root)
{
osg::Geode* terrainGeode = new osg::Geode;
// create terrain
{
osg::StateSet* stateset = new osg::StateSet();
osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
if (image)
{
osg::Texture2D* texture = new osg::Texture2D;
texture->setImage(image);
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
rs = new Producer::RenderSurface;
rs->setWindowRectangle(0,0,1,1);
rs->useBorder(false);
rs->useConfigEventThread(false);
rs->realize();
std::cout<<"Realized window"<<std::endl;
}
terrainGeode->setStateSet( stateset );
float size = 1000; // 10km;
float scale = size/39.0f; // 10km;
float z_scale = scale*3.0f;
osg::HeightField* grid = new osg::HeightField;
grid->allocateGrid(38,39);
grid->setXInterval(scale);
grid->setYInterval(scale);
for(unsigned int r=0;r<39;++r)
virtual ~GraphicsContext()
{
for(unsigned int c=0;c<38;++c)
{
grid->setHeight(c,r,z_scale*vertex[r+c*39][2]);
}
}
terrainGeode->addDrawable(new osg::ShapeDrawable(grid));
root->addChild(terrainGeode);
}
private:
Producer::ref_ptr<Producer::RenderSurface> rs;
};
// create sphere segment
{
osgSim::SphereSegment* ss = new osgSim::SphereSegment(
computeTerrainIntersection(terrainGeode,550.0f,780.0f), // center
500.0f, // radius
osg::DegreesToRadians(135.0f),
osg::DegreesToRadians(245.0f),
osg::DegreesToRadians(-10.0f),
osg::DegreesToRadians(30.0f),
60);
ss->setAllColors(osg::Vec4(1.0f,1.0f,1.0f,0.5f));
ss->setSideColor(osg::Vec4(0.0f,1.0f,1.0f,0.1f));
root->addChild(ss);
}
// create particle effects
{
osg::PositionAttitudeTransform* positionEffects = new osg::PositionAttitudeTransform;
positionEffects->setPosition(computeTerrainIntersection(terrainGeode,100.0f,100.0f));
root->addChild(positionEffects);
osgParticle::ExplosionEffect* explosion = new osgParticle::ExplosionEffect;
osgParticle::SmokeEffect* smoke = new osgParticle::SmokeEffect;
osgParticle::FireEffect* fire = new osgParticle::FireEffect;
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),10.0f)));
positionEffects->addChild(geode);
positionEffects->addChild(explosion);
positionEffects->addChild(smoke);
positionEffects->addChild(fire);
osgParticle::ParticleSystemUpdater *psu = new osgParticle::ParticleSystemUpdater;
psu->addParticleSystem(explosion->getParticleSystem());
psu->addParticleSystem(smoke->getParticleSystem());
psu->addParticleSystem(fire->getParticleSystem());
// add the updater node to the scene graph
root->addChild(psu);
}
osg::Node* createEarth()
{
osg::ref_ptr<osg::Node> scene;
// create the moving models.
{
root->addChild(createMovingModel(osg::Vec3(500.0f,500.0f,500.0f),100.0f));
std::string filename = osgDB::findDataFile("Images/land_shallow_topo_2048.jpg");
osg::ref_ptr<osgTerrain::DataSet> dataSet = new osgTerrain::DataSet;
// register the source imagery
{
osgTerrain::DataSet::Source* source = new osgTerrain::DataSet::Source(osgTerrain::DataSet::Source::IMAGE, filename);
source->setCoordinateSystemPolicy(osgTerrain::DataSet::Source::PREFER_CONFIG_SETTINGS);
source->setCoordinateSystem(osgTerrain::DataSet::coordinateSystemStringToWTK("WGS84"));
source->setGeoTransformPolicy(osgTerrain::DataSet::Source::PREFER_CONFIG_SETTINGS_BUT_SCALE_BY_FILE_RESOLUTION);
source->setGeoTransformFromRange(-180.0, 180.0, -90.0, 90.0);
dataSet->addSource(source);
}
// set up destination database paramters.
dataSet->setDatabaseType(osgTerrain::DataSet::LOD_DATABASE);
dataSet->setConvertFromGeographicToGeocentric(true);
dataSet->setDestinationName("test.osg");
// load the source data and record sizes.
dataSet->loadSources();
GraphicsContext context;
dataSet->createDestination(30);
if (dataSet->getDatabaseType()==osgTerrain::DataSet::LOD_DATABASE) dataSet->buildDestination();
else dataSet->writeDestination();
scene = dataSet->getDestinationRootNode();
}
return scene.release();
}
class FindNamedNodeVisitor : public osg::NodeVisitor
{
public:
@ -275,11 +105,6 @@ public:
//////////////////////////////////////////////////////////////////////////////
// main()
//////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
// use an ArgumentParser object to manage the program arguments.
@ -319,8 +144,9 @@ int main(int argc, char **argv)
return 1;
}
osg::Group *root = new osg::Group;
build_world(root);
osg::Node *root = createEarth();
if (!root) return 0;
// add a viewport to the viewer and attach the scene graph.
viewer.setSceneData(root);

View File

@ -921,6 +921,9 @@ class OSGTERRAIN_EXPORT DataSet : public osg::Referenced
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; }
@ -1015,7 +1018,8 @@ class OSGTERRAIN_EXPORT DataSet : public osg::Referenced
protected:
virtual ~DataSet() {}
void _readRow(Row& row);
void _equalizeRow(Row& row);
void _writeRow(Row& row);

View File

@ -1932,7 +1932,8 @@ osg::StateSet* DataSet::DestinationTile::createStateSet()
{
if (!_imagery.valid() || !_imagery->_image.valid()) return 0;
std::string imageName(_name+".rgb");
std::string imageExension(".dds"); // ".rgb"
std::string imageName(_name+imageExension);
_imagery->_image->setFileName(imageName.c_str());
osg::StateSet* stateset = new osg::StateSet;
@ -1968,7 +1969,7 @@ osg::StateSet* DataSet::DestinationTile::createStateSet()
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
bool inlineImageFile = _dataSet->getDestinationTileExtension()==".ive";
bool compressedImageSupported = inlineImageFile;
bool compressedImageSupported = inlineImageFile || imageExension==".dds";
bool mipmapImageSupported = inlineImageFile;
if (compressedImageSupported &&
@ -2013,12 +2014,6 @@ osg::StateSet* DataSet::DestinationTile::createStateSet()
}
}
if (!inlineImageFile)
{
osg::notify(osg::INFO)<<"Writing out imagery to "<<imageName<<std::endl;
osgDB::writeImageFile(*_imagery->_image,_imagery->_image->getFileName().c_str());
}
return stateset;
}
@ -2100,7 +2095,7 @@ osg::Node* DataSet::DestinationTile::createPolygonal()
osg::notify(osg::INFO)<<"--------- DataSet::DestinationTile::createDrawableGeometry() ------------- "<<std::endl;
const osg::EllipsoidModel* et = _dataSet->getEllipsoidModel();
bool mapLatLongsToXYZ = _dataSet->getConvertFromGeographicToGeocentric() && et;
bool mapLatLongsToXYZ = _dataSet->mapLatLongsToXYZ();
bool useLocalToTileTransform = _dataSet->getUseLocalTileTransform();
osg::ref_ptr<osg::HeightField> grid = 0;
@ -2761,6 +2756,8 @@ osg::Node* DataSet::CompositeDestination::createScene()
osg::LOD* lod = new osg::LOD;
float farDistance = _dataSet->getMaximumVisibleDistanceOfTopLevel();
unsigned int childNum = 0;
for(RangeNodeListMap::reverse_iterator rnitr=rangeNodeListMap.rbegin();
rnitr!=rangeNodeListMap.rend();
@ -2772,7 +2769,7 @@ osg::Node* DataSet::CompositeDestination::createScene()
if (childNum==0)
{
// by deafult make the first child have a very visible distance so its always seen
maxVisibleDistance = 1e10;
maxVisibleDistance = farDistance;
}
else
{
@ -2903,7 +2900,7 @@ osg::Node* DataSet::CompositeDestination::createPagedLODScene()
pagedLOD->addChild(group);
}
cutOffDistance = pagedLOD->getBound().radius()*_dataSet->getRadiusToMaxVisibleDistanceRatio();
// cutOffDistance = pagedLOD->getBound().radius()*_dataSet->getRadiusToMaxVisibleDistanceRatio();
pagedLOD->setRange(0,cutOffDistance,farDistance);
@ -3067,7 +3064,18 @@ DataSet::CompositeDestination* DataSet::createDestinationGraph(CompositeDestinat
DataSet::CompositeDestination* destinationGraph = new DataSet::CompositeDestination(cs,extents);
destinationGraph->_maxVisibleDistance = extents.radius()*getRadiusToMaxVisibleDistanceRatio();
if (mapLatLongsToXYZ())
{
// we need to project the extents into world coords to get the appropriate size to use for control max visible distance
float max_range = osg::maximum(extents.xMax()-extents.xMin(),extents.yMax()-extents.yMin());
float projected_radius = osg::DegreesToRadians(max_range) * getEllipsoidModel()->getRadiusEquator();
float center_offset = (max_range/360.0f) * getEllipsoidModel()->getRadiusEquator();
destinationGraph->_maxVisibleDistance = projected_radius * getRadiusToMaxVisibleDistanceRatio() + center_offset;
}
else
{
destinationGraph->_maxVisibleDistance = extents.radius()*getRadiusToMaxVisibleDistanceRatio();
}
// first create the topmost tile
@ -3597,6 +3605,51 @@ void DataSet::_equalizeRow(Row& row)
}
}
class WriteImageFilesVisitor : public osg::NodeVisitor
{
public:
WriteImageFilesVisitor():
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
virtual void apply(osg::Node& node)
{
if (node.getStateSet()) apply(*(node.getStateSet()));
traverse(node);
}
virtual void apply(osg::Geode& geode)
{
if (geode.getStateSet()) apply(*(geode.getStateSet()));
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
if (geode.getDrawable(i)->getStateSet()) apply(*(geode.getDrawable(i)->getStateSet()));
}
traverse(geode);
}
void apply(osg::StateSet& stateset)
{
for(unsigned int i=0;i<stateset.getTextureAttributeList().size();++i)
{
osg::Image* image = 0;
osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(stateset.getTextureAttribute(i,osg::StateAttribute::TEXTURE));
if (texture2D) image = texture2D->getImage();
if (image)
{
osg::notify(osg::INFO)<<"Writing out imagery to "<<image->getFileName()<<std::endl;
osgDB::writeImageFile(*image,image->getFileName().c_str());
}
}
}
};
void DataSet::_writeRow(Row& row)
{
osg::notify(osg::NOTICE)<<"_writeRow "<<row.size()<<std::endl;
@ -3648,6 +3701,12 @@ void DataSet::_writeRow(Row& row)
{
osg::notify(osg::NOTICE)<<" writeNodeFile = "<<cd->_level<<" X="<<cd->_tileX<<" Y="<<cd->_tileY<<" filename="<<filename<<std::endl;
osgDB::writeNodeFile(*node,filename);
if (_tileExtension==".osg")
{
WriteImageFilesVisitor wifv;
node->accept(wifv);
}
}
else
{
@ -3715,7 +3774,15 @@ void DataSet::_buildDestination(bool writeToDisk)
_rootNode->addDescription(_comment);
}
if (writeToDisk) osgDB::writeNodeFile(*_rootNode,filename);
if (writeToDisk)
{
osgDB::writeNodeFile(*_rootNode,filename);
if (_tileExtension==".osg")
{
WriteImageFilesVisitor wifv;
_rootNode->accept(wifv);
}
}
}
else // _databaseType==PagedLOD_DATABASE
{
@ -3748,7 +3815,10 @@ void DataSet::_buildDestination(bool writeToDisk)
}
_equalizeRow(prev_itr->second);
if (writeToDisk) _writeRow(prev_itr->second);
if (writeToDisk)
{
_writeRow(prev_itr->second);
}
}
}
osg::notify(osg::NOTICE)<<"completed DataSet::writeDestination("<<filename<<")"<<std::endl;