From bbef23deaea8c89190f01185b413359585d6e3ea Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Tue, 2 Feb 2021 15:15:18 +0000 Subject: [PATCH] WS30: Terrasync compatible files, LoD control Change WS30 file format to match standard scenery directory structure, add controls for LOD ranges. --- simgear/bucket/newbucket.cxx | 45 +++++++++--------- simgear/scene/model/ModelRegistry.cxx | 49 +++++++++++++++++-- simgear/scene/tgdb/VPBTechnique.cxx | 65 ++------------------------ simgear/scene/tgdb/VPBTechnique.hxx | 2 - simgear/scene/util/SGSceneFeatures.hxx | 20 ++++++++ 5 files changed, 93 insertions(+), 88 deletions(-) diff --git a/simgear/bucket/newbucket.cxx b/simgear/bucket/newbucket.cxx index 27fcc504..6832b423 100644 --- a/simgear/bucket/newbucket.cxx +++ b/simgear/bucket/newbucket.cxx @@ -192,39 +192,40 @@ std::string SGBucket::gen_vpb_base() const { top_lon = lon / 10; main_lon = lon; - if ((lon < 0) && (top_lon * 10 != lon)) { - top_lon -= 1; + if ( (lon < 0) && (top_lon * 10 != lon) ) { + top_lon -= 1; } top_lon *= 10; - if (top_lon >= 0) { - hem = 'E'; + if ( top_lon >= 0 ) { + hem = 'e'; + } else { + hem = 'w'; + top_lon *= -1; } - else { - hem = 'W'; - top_lon *= -1; + if ( main_lon < 0 ) { + main_lon *= -1; } - if (main_lon < 0) { - main_lon *= -1; - } - + top_lat = lat / 10; main_lat = lat; - if ((lat < 0) && (top_lat * 10 != lat)) { - top_lat -= 1; + if ( (lat < 0) && (top_lat * 10 != lat) ) { + top_lat -= 1; } top_lat *= 10; - if (top_lat >= 0) { - pole = 'N'; + if ( top_lat >= 0 ) { + pole = 'n'; + } else { + pole = 's'; + top_lat *= -1; } - else { - pole = 'S'; - top_lat *= -1; - } - if (main_lat < 0) { - main_lat *= -1; + if ( main_lat < 0 ) { + main_lat *= -1; } - ::snprintf(raw_path, 256, "WS_%c%d%c%2d", hem, main_lon, pole, main_lat); + ::snprintf(raw_path, 256, "%c%03d%c%02d/%c%03d%c%02d/ws_%c%03d%c%02d", + hem, top_lon, pole, top_lat, + hem, main_lon, pole, main_lat, + hem, main_lon, pole, main_lat); return raw_path; } diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index b9008a5b..531eb2b3 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -937,6 +937,40 @@ public: } }; +class AdjustLODVisitor : public osg::NodeVisitor +{ +public: + float _rangeFactor; + float _maxRange; + AdjustLODVisitor(float rangeFactor, float maxRange): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) + { + _rangeFactor = rangeFactor; + _maxRange = maxRange; + } + + void apply(osg::PagedLOD& node) + { + if (node.getNumChildren() == 0) return; + + if (node.getNumFileNames() == 2) { + // We use internal knowledge of VPB to modify the LOD ranges. + // The first child is the current node. The second is the sub-tile at higher resolution. + // See VirtualPlanetBuild src/vpb/Destination.cpp CompositeDestination::createPagedLODScene() + // lines 3330-3333 + node.dirtyBound(); // At this point the bounds haven't been calculated, so we need to force this. + float maxRange = _maxRange + node.getBound().radius(); + float cutoff = std::min(node.getBound().radius() * _rangeFactor, maxRange); + SG_LOG(SG_TERRAIN, SG_DEBUG, "VPB PagedLOD range " << cutoff << " " << maxRange); + node.setRange(0, cutoff, maxRange); + node.setRange(1, 0, cutoff); + } else { + SG_LOG(SG_TERRAIN, SG_ALERT, "Unexpected PagedLOD type in LOD range update"); + } + + traverse(node); + } +}; + struct OSGOptimizePolicy : public OptimizeModelPolicy { @@ -950,27 +984,34 @@ struct OSGOptimizePolicy : public OptimizeModelPolicy { { ref_ptr optimized = node; - const SGReaderWriterOptions* sgopt - = dynamic_cast(opt); + const SGReaderWriterOptions* sgopt = SGReaderWriterOptions::copyOrCreate(opt); - if (fileName.find("vpb/WS_") != string::npos) { + if (fileName.find("ws_") != string::npos) { // Currently the only way we have to identify WS3.0 / VirtualPlanetBuilder files is by the filename // Clean out any existing osgTerrain techniques CleanTechniqueVisitor ctv; optimized->accept(ctv); + // Adjust the LOD ranges as required. + double rangeFactor = SGSceneFeatures::instance()->getVPBRangeFactor(); + double maxRange = SGSceneFeatures::instance()->getVPBMaxRange(); + AdjustLODVisitor alv = AdjustLODVisitor(rangeFactor, maxRange); + optimized->accept(alv); + osg::ref_ptr terrain = findTopMostNodeOfType(optimized.get()); if (terrain != NULL) { // Top level terrain->setSampleRatio(1.0); terrain->setVerticalScale(1.0); - terrain->setBlendingPolicy(osgTerrain::TerrainTile::INHERIT); terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt)); } else { // no Terrain node present insert one above the loaded model. terrain = new osgTerrain::Terrain; + terrain->setSampleRatio(1.0); + terrain->setVerticalScale(1.0); + terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt)); //SG_LOG(SG_TERRAIN, SG_ALERT, "Creating Terrain Node for " << fileName); // if CoordinateSystemNode is present copy it's contents into the Terrain, and discard it. diff --git a/simgear/scene/tgdb/VPBTechnique.cxx b/simgear/scene/tgdb/VPBTechnique.cxx index 5209f454..1b7173c6 100644 --- a/simgear/scene/tgdb/VPBTechnique.cxx +++ b/simgear/scene/tgdb/VPBTechnique.cxx @@ -37,9 +37,10 @@ #include -#include #include #include +#include +#include #include "VPBTechnique.hxx" @@ -156,14 +157,12 @@ void VPBTechnique::init(int dirtyMask, bool assumeMultiThreaded) else { applyColorLayers(*buffer, masterLocator); - applyTransparency(*buffer); } } else { generateGeometry(*buffer, masterLocator, centerModel); applyColorLayers(*buffer, masterLocator); - applyTransparency(*buffer); } if (buffer->_transform.valid()) buffer->_transform->setThreadSafeRefUnref(true); @@ -847,11 +846,10 @@ void VPBTechnique::generateGeometry(BufferData& buffer, Locator* masterLocator, numRows = elevationLayer->getNumRows(); } - double scaleHeight = atof(_options->getPluginStringData("SimGear::ELEV_MESH_VERTICAL_SCALE").c_str()); - double sampleRatio = atof(_options->getPluginStringData("SimGear::ELEV_MESH_SAMPLE_RATIO").c_str()); - double constraint_gap = atof(_options->getPluginStringData("SimGear::ELEV_MESH_CONSTRAINT_GAP").c_str()); - // OSG_NOTICE<<"Sample ratio="<getVPBVerticalScale(); + double sampleRatio = SGSceneFeatures::instance()->getVPBSampleRatio(); + double constraint_gap = SGSceneFeatures::instance()->getVPBConstraintGap(); unsigned int minimumNumColumns = 16u; unsigned int minimumNumRows = 16u; @@ -865,8 +863,6 @@ void VPBTechnique::generateGeometry(BufferData& buffer, Locator* masterLocator, numRows = std::max((unsigned int) (float(originalNumRows)*sqrtf(sampleRatio)),minimumNumRows); } - - bool treatBoundariesToValidDataAsDefaultValue = _terrainTile->getTreatBoundariesToValidDataAsDefaultValue(); OSG_INFO<<"TreatBoundariesToValidDataAsDefaultValue="<getBlendingPolicy(); - if (blendingPolicy == TerrainTile::INHERIT && _terrainTile->getTerrain()) - { - OSG_INFO<<"VPBTechnique::applyTransparency() inheriting policy from Terrain"<getTerrain()->getBlendingPolicy(); - } - - if (blendingPolicy == TerrainTile::INHERIT) - { - OSG_INFO<<"VPBTechnique::applyTransparency() policy is INHERIT, defaulting to ENABLE_BLENDING_WHEN_ALPHA_PRESENT"<getNumColorLayers(); ++i) - { - osg::Image* image = (_terrainTile->getColorLayer(i)!=0) ? _terrainTile->getColorLayer(i)->getImage() : 0; - if (image) - { - enableBlending = image->isImageTranslucent(); - break; - } - } - } - - if (enableBlending) - { - osg::StateSet* stateset = buffer._geode->getOrCreateStateSet(); - stateset->setMode(GL_BLEND, osg::StateAttribute::ON); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - } - -} - void VPBTechnique::update(osg::NodeVisitor& nv) { if (_terrainTile) _terrainTile->osg::Group::traverse(nv); diff --git a/simgear/scene/tgdb/VPBTechnique.hxx b/simgear/scene/tgdb/VPBTechnique.hxx index 1668f269..c6d2022d 100644 --- a/simgear/scene/tgdb/VPBTechnique.hxx +++ b/simgear/scene/tgdb/VPBTechnique.hxx @@ -115,8 +115,6 @@ class VPBTechnique : public TerrainTechnique virtual void applyColorLayers(BufferData& buffer, Locator* masterLocator); - virtual void applyTransparency(BufferData& buffer); - OpenThreads::Mutex _writeBufferMutex; osg::ref_ptr _currentBufferData; osg::ref_ptr _newBufferData; diff --git a/simgear/scene/util/SGSceneFeatures.hxx b/simgear/scene/util/SGSceneFeatures.hxx index 128cb33a..7b3a32bd 100644 --- a/simgear/scene/util/SGSceneFeatures.hxx +++ b/simgear/scene/util/SGSceneFeatures.hxx @@ -64,6 +64,21 @@ public: bool getVPBActive() const { return _VPBActive; } void setVPBActive(const bool val) { _VPBActive = val; } + float getVPBRangeFactor() const { return _VPBRangeFactor; } + void setVPBRangeFactor(const float val) { _VPBRangeFactor = val; } + + float getVPBMaxRange() const { return _VPBMaxRange; } + void setVPBMaxRange(const float val) { _VPBMaxRange = val; } + + float getVPBConstraintGap() const { return _VPBConstraintGap; } + void setVPBConstraintGap(const float val) { _VPBConstraintGap = val; } + + float getVPBSampleRatio() const { return _VPBSampleRatio; } + void setVPBSampleRatio(const float val) { _VPBSampleRatio = val; } + + float getVPBVerticalScale() const { return _VPBVerticalScale; } + void setVPBVerticalScale(const float val) { _VPBVerticalScale = val; } + void setEnablePointSpriteLights(bool enable) { _pointSpriteLights = enable; @@ -150,6 +165,11 @@ private: bool _distanceAttenuationLights; int _textureFilter; bool _VPBActive; + float _VPBConstraintGap; + float _VPBRangeFactor; + float _VPBMaxRange; + float _VPBSampleRatio; + float _VPBVerticalScale; }; #endif