From b664c20c74510f52a892b17dc39db1957e9774e6 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 13 Sep 2004 13:53:45 +0000 Subject: [PATCH] Improved the handling of building/writing generated databases, and the fixed transition distances on the lower levels of geocentric databases. --- examples/osgsimulation/GNUmakefile | 2 +- examples/osgsimulation/osgsimulation.cpp | 290 +++++------------------ include/osgTerrain/DataSet | 6 +- src/osgTerrain/DataSet.cpp | 98 ++++++-- 4 files changed, 148 insertions(+), 248 deletions(-) diff --git a/examples/osgsimulation/GNUmakefile b/examples/osgsimulation/GNUmakefile index 0f459affe..634331b33 100644 --- a/examples/osgsimulation/GNUmakefile +++ b/examples/osgsimulation/GNUmakefile @@ -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)\ diff --git a/examples/osgsimulation/osgsimulation.cpp b/examples/osgsimulation/osgsimulation.cpp index 93f787da9..76a4d9ce0 100644 --- a/examples/osgsimulation/osgsimulation.cpp +++ b/examples/osgsimulation/osgsimulation.cpp @@ -6,251 +6,81 @@ #include #include #include +#include +#include #include #include -#include - -#include -#include -#include -#include +#include #include -// 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;iinsert(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 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"<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 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 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 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); diff --git a/include/osgTerrain/DataSet b/include/osgTerrain/DataSet index 5c0495a5c..e0a823225 100644 --- a/include/osgTerrain/DataSet +++ b/include/osgTerrain/DataSet @@ -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); diff --git a/src/osgTerrain/DataSet.cpp b/src/osgTerrain/DataSet.cpp index 924f4ba1b..a2cb0ca19 100644 --- a/src/osgTerrain/DataSet.cpp +++ b/src/osgTerrain/DataSet.cpp @@ -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 "<_image,_imagery->_image->getFileName().c_str()); - } - return stateset; } @@ -2100,7 +2095,7 @@ osg::Node* DataSet::DestinationTile::createPolygonal() osg::notify(osg::INFO)<<"--------- DataSet::DestinationTile::createDrawableGeometry() ------------- "<getEllipsoidModel(); - bool mapLatLongsToXYZ = _dataSet->getConvertFromGeographicToGeocentric() && et; + bool mapLatLongsToXYZ = _dataSet->mapLatLongsToXYZ(); bool useLocalToTileTransform = _dataSet->getUseLocalTileTransform(); osg::ref_ptr 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;igetStateSet()) apply(*(geode.getDrawable(i)->getStateSet())); + } + + traverse(geode); + } + + void apply(osg::StateSet& stateset) + { + for(unsigned int i=0;i(stateset.getTextureAttribute(i,osg::StateAttribute::TEXTURE)); + if (texture2D) image = texture2D->getImage(); + + if (image) + { + osg::notify(osg::INFO)<<"Writing out imagery to "<getFileName()<getFileName().c_str()); + } + } + } +}; + void DataSet::_writeRow(Row& row) { osg::notify(osg::NOTICE)<<"_writeRow "<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("<